class vehicles:
class car:
def drive():
pass
car1 = car()
car2 = car()
car3 = car()
Is there a way I can call the drive function on all the cars in one call, without naming each explicitly.
class vehicles:
class car:
def drive():
pass
car1 = car()
car2 = car()
car3 = car()
Is there a way I can call the drive function on all the cars in one call, without naming each explicitly.
If you really want that, you have to design it into your model - so that, for example, you have a registry of all created cars.
It is not a hard thing to do - I think the most obvious way is to customize the
__new__
method in your class to keep that registry, and make the calls:
class Base:
def __new__(cls, *args, **kw):
self = super.__new__(*args, **kw)
if not hasattr(cls, _instances):
cls._instances = []
cls._instances.append(self)
return self
@classmethod
def call_all(cls, method_name, *args, **kw):
results = []
for instance in cls._instances:
results.append(getattr(instance, method_name)(*args, **kw))
return results
def __del__(self):
self.__class__._instances.remoce(self)
class vehicles:
class car(Base):
def drive():
pass
car1 = car()
car2 = car()
car3 = car()
car.call_all("drive")
Another way, since this is class level things that should be kept when classes are created, could be dealt with in metaclasses. The good: it would be "pure" and you would not have special processing that happens when you instantiate the first object of that class as above. The bad: classes with different metaclasses are hard to combine - and if you have a class hierarchy in which some classes need this behavior, and some not - doing this at class level keeps everything interchangeable.
Actually, note that creating the superclass Base
is an optional step. If you are only using it in one place in all your project, the logic could very well be inside the car
class itself (as is in the answer by Narcise, bellow.)
If you don't want to do that, you can use the garbage collector (gc
) module to find out all instances of your object and call the method on them. I don't think that would be a ice thing to do, as the gc
itself is an
implementation detail for cPython.
import gc
...
for obj in gc.get_referrers(car):
if not isinstance(obj, car): continue
obj.drive()
or in an ugly oneliner:
[getattr(obj, "drive")() for obj in gc.get_referrers(car) if isinstance(obj, car)]
class Vehicule():
pos, child = 0, []
def __init__(self):
self.__class__.child.append(self)
self.pos = self.__class__.pos
self.__class__.pos +=1
def cond(self):
print self.pos
@classmethod
def drive(cls):
for v in cls.child:
v.cond()
testing:
t = Vehicule()
c = Vehicule()
g = Vehicule()
Vehicule.drive()
>>0
>>1
>>2
To answer your question, yes there is a way. You can use a class variable to keep track of instances.
class vehicles:
working_vehicles = [] # this is a class variable
class car:
def __init__(self):
vehicles.working_vehicles.append(self) # adds itself to working_vehicles
def drive(self):
pass
You can then create instances, and access them from vehicles.working_vehicles
.
Demo:
First create the cars:
>>> car1 = vehicles.car()
>>> car2 = vehicles.car()
>>> car3 = vehicles.car()
Then access them from vehicles.working_vehicles
.
>>> print(vehicles.working_vehicles)
[<__main__.vehicles.car object at 0x022DF6F0>, <__main__.vehicles.car object at 0x01E97ED0>, <__main__.vehicles.car object at 0x01EAA6B0>]
Which isn't really helpful visually, but you can call the drive
method on all the cars, like this:
>>> for car in vehicles.working_vehicles:
... car.drive()
Or in one line:
>>> map(lambda car: car.drive(), vehicles.working_vehicles)
Which won't immediately drive the cars. You would need to call list
on the map
iterator.