Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is code outside a class definition run when only the class is imported?

EXPECTATION
I want to import a python class from another file without importing the rest of the file.

PROBLEM
When I import the class using from Exercise_7 import Vehicle (Vehicle being the class), and then run my code it seems that lines from Exercise_7.py that are outside the class definition also run.

CODE

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Exercise_7.py :

import numpy as np

class Vehicle:
  def __init__(self, typeOfVehicle, velocity, colour, electric):
    self.typeOfVehicle = str(typeOfVehicle)
    self.velocity = tuple(velocity)
    self.velocity = np.array(self.velocity)
    self.colour = str(colour)
    self.electric = bool(electric)
      
  def updateVelocity(self, velocityTuple):
    self.velocity = np.array(velocityTuple)

  def allAttributes(self):
    attributes = [self.typeOfVehicle, self.velocity, self.colour, self.electric]
    print(attributes)

  def emissions(self, distance):
    #electric vehicles
    if self.electric == True:
      if self.typeOfVehicle == "Car":
        emission = 1*distance
      elif self.typeOfVehicle == "Truck":
        emission = 5*distance

    else:  #vehicle is not electric
      if self.typeOfVehicle == "Car":
        emission = 10*distance
      elif self.typeOfVehicle == "Truck":
        emission = 50*distance
    return emission

#---TEST CODE THAT IS BEING RUN (when I don't want it to)--- 

vehicle1 = Vehicle("Car", (3,5), "red", False)
vehicle1.updateVelocity((2,6))
vehicle1.allAttributes()
print(vehicle1.emissions(100))

Exercise_8.py (The file that when run, runs the unwanted code) :

from Exercise_7 import Vehicle
import numpy as np
import random as r

def newVehicles(type, electric1):
    colours = ["red", "blue", "green", "black", "grey"]
    for i in range(0,50):
        velocity = (r.uniform(1,70), r.uniform(1,70))
        newVehicle = Vehicle(type, velocity, colours[r.randint(0,4)], electric1)
        vehicles.append(newVehicle)

def createVehicles():
    newVehicles("Car", True)
    newVehicles("Car", False)
    newVehicles("Truck", True)
    newVehicles("Truck", False)
    return vehicles

def calculateEmissions(vehicles, time):
    electricCarsEmissions = 0
    nonelectricCarsEmissions = 0
    electricTrucksEmissions = 0
    nonelectricTrucksEmissions = 0
    for vehicle in vehicles:
        speed = (vehicle.velocity[0]**2 + vehicle.velocity[1]**2)**1/2
        distanceTravelled = speed*time
        vehicle.distance = distanceTravelled
        emission = vehicle.emissions(distanceTravelled)
        if vehicle.typeOfVehicle == "Car" and vehicle.electric == True:
            electricCarsEmissions += emission
        elif vehicle.typeOfVehicle == "Car" and vehicle.electric == False:
            nonelectricCarsEmissions += emission
        elif vehicle.typeOfVehicle == "Truck" and vehicle.electric == True:
            electricTrucksEmissions += emission
        elif vehicle.typeOfVehicle == "Truck" and vehicle.electric == False:
            nonelectricTrucksEmissions += emission
    return electricCarsEmissions, nonelectricCarsEmissions, electricTrucksEmissions, nonelectricTrucksEmissions
    
    
vehicles = []
listOfVehicles = createVehicles()
print(calculateEmissions(listOfVehicles, 20))

When Exercise_8.py is run, it outputs this :

['Car', array([2, 6]), 'red', False]  #output from Exercise_7.py code
1000 #output from Exercise_7.py code
(1836161.109986278, 16586342.282856379, 7901210.428254995, 74406974.7703749) #desired output

>Solution :

Modules are blocks of executable code, as are def and class statements. They are only well-defined in their entire context of code. As such, it is not possible to load only parts of a module.

Running from Exercise_7 import Vehicle loads the entire module Exercise_7 into the interpreter but only imports the name Vehicle into the file.


Code that is not supposed to run during regular imports should be in a __main__ guard instead:

if __name__ == "__main__":
    vehicle1 = Vehicle("Car", (3,5), "red", False)
    vehicle1.updateVelocity((2,6))
    vehicle1.allAttributes()
    print(vehicle1.emissions(100))

Loosely speaking, a module is __main__ only when directly executed – e.g. as python -m Exercise_7 – but not when imported by another module.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading