在对象的所有实例上调用方法

Chr*_*sen 3 python python-3.x

class vehicles:
    class car:
        def drive():
            pass

car1 = car()
car2 = car()
car3 = car()
Run Code Online (Sandbox Code Playgroud)

有没有办法可以在一次通话中调用所有车辆上的驱动功能,而无需明确指定每个车辆.

jsb*_*eno 5

如果你真的想要它,你必须将它设计到你的模型中 - 例如,你有一个所有创建汽车的注册表.

这不是一件难事 - 我认为最明显的方法是__new__在类中自定义 方法以保留该注册表并进行调用:

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")
Run Code Online (Sandbox Code Playgroud)

另一种方式,因为这是在创建类时应该保留的类级别事物,可以在元类中处理.好处:它将是"纯粹的",当您实例化上述类的第一个对象时,您将不会遇到特殊处理.坏处理:具有不同元类的类很难组合 - 如果你有一个类层次结构,其中某些类需要这种行为,而另一些类则不需要 - 在类级别执行此操作可使所有内容保持可互换.

实际上,请注意,创建超类Base是一个可选步骤.如果你只是在你所有项目中的一个地方使用它,逻辑很可能就在car课堂内部(正如Narcise的回答,吼叫.)

如果您不想这样做,可以使用garbage collector(gc)模块找出对象的所有实例并在其上调用方法.我认为这不是一件好事,因为它gc本身就是cPython的一个实现细节.

import gc

...
for obj in gc.get_referrers(car):
     if not isinstance(obj, car): continue
     obj.drive()
Run Code Online (Sandbox Code Playgroud)

或者在一个丑陋的oneliner:

[getattr(obj, "drive")() for obj in gc.get_referrers(car) if isinstance(obj, car)]
Run Code Online (Sandbox Code Playgroud)