While adding attributes from outside the class definition is possible, it is no good style.
I recommend to define attributes in the init constructor. This way it is guarantied to be present in the final object.
class A():
def __init__(self, b):
self.b = b
class B():
def __init__(self, a):
self.a = a
This design has a big issue. It creates a circle dependency. You can’t create one object without the other. But you can create only one object at the time.
So we need to set the reference to a/b at a later time:
class A():
def __init__(self):
self.b = None
class B():
def __init__(self):
self.a = None
a = A()
b = B()
a.b = b
b.a = a
This guaranties the attributes are always there, but they can contain None.
A middle way would be to provide both options:
class A():
def __init__(self, b=None):
self.b = b
class B():
def __init__(self, a=None):
self.a = a
a = A()
b = B(a)
a.b = b # close the circle
If you want to ensure to create completely setup objects and the objects can’t do it by themselves, you can use a factory function:
def createAB():
a = A()
b = B(a)
a.b = b
return a,b
a,b = createAB()
Ensure always to use this function when you want to create a and b.
If you want to create instances of other classes in a class you get a factory class:
def ABFactory():
def create(self):
a = A()
b = B(a)
a.b = a
return a,b
factory = ABFactory()
a,b = factory.create()
Why creating a class to do such do that? I know you want have a car project. Now imagine you want to create objects regarding different kind of cars. So you can create factories that can create a certain car with all it’s sub-components and relationships.
Finally you get a car, regardless what kind of car:
class Vehicle:
...
class Truck(Vehicle):
...
class Roadstar(Vehicle):
...
class Bike(Vehicle):
...
class TrackFactory():
def create(self):
...
return track
class RoadstarFactory():
def create(self):
...
return roadstar
class BikeFaktory():
def create(self).
...
return bike
By using any of the factories you always get a Vehicle, but a specific one.
def buildMyVehicle(factory):
vehicle = factory.create()
ower["myVehicle"] = vehicle
def driveForward():
owner["myVehicle"].drive(0.3)
For example you could have selected a specific factory at the vehicle selection menu. So the player choose to create a Truck, so you setup the TruckFactory. When entering the Track-level, you do not care what factory it is, you tell it to create a vehicle and you get one.
What is the difference between Factory class an Factory function? What the above example doe not show is that you can give the factory certain setup attributes (e.g. number of wheels, engine class) it should use. If you use the Factory function you need to provide that as parameter, which does not always fit.
class TrackFactory():
def __init__(self, numberOfWheels, engine):
self.numberOfWheels = numberOfWheels
self.engine = engine
def create(self):
truck = Truck()
for wheel in range(self.numberOfWheels):
self.createWheel(truck)
truck.engine = engine
engine.vehicle = truck
return truck
threeAxisTruckFactory = TrackFactory(6, DieselEngine())
twoAxisTruckFactory = TrackFactory(4, DieselEngine())
One the other side a bike always has two wheels. So there is no need to tell the number:
class BikeFactory():
def __init__(self, engine):
self.numberOfWheels = 2
self.engine = engine
...
I hope this does not confuse you too much