将多个类方法应用于对象列表的Pythonic方式

我有一个带有一些内置方法的类。这是该类的抽象示例:

class Foo:
    def __init__(self):
        self.a = 0
        self.b = 0

    def addOneToA(self):
        self.a += 1

    def addOneToB(self):
        self.b += 1

为简单起见,我将内置方法总数减少到 2 个,但实际上我的类有接近 20 个。

接下来,我有另一个类,旨在处理Foo实例列表。

class Bar:
    def __init__(self, fooInstances):
        self.fooInstances = fooInstances

# Bar([Foo(), Foo(), Foo()])

如果我想将其中一种Foo方法应用于 中的Foo实例Bar怎么办?

class Bar:
    # ...
    def addOneToA(self):
        for fooInstance in self.fooInstances:
            fooInstance.addOneToA()
    
    def addOneToB(self):
        for fooInstance in self.fooInstances:
            fooInstance.addOneToB()

上面的例子是我描述的一种方法,但是如果有 20 个Foo. 或者,我可以做这样的事情:

class Bar:
    # ...
    def applyFooMethod(self, func, *args):
        for fooInstance in self.fooInstances:
            fooInstance.func(args)

但我宁愿有一些会允许我这样称呼.addOneToA()Bar,并把它应用到所有Foo的情况Bar。有没有一种干净的方法来做到这一点而无需定义Fooinside 的所有方法Bar

回答

一种方法是覆盖__getattr__Bar

class Bar:
    def __init__(self, fooInstances):
        self.fooInstances = fooInstances

    def __getattr__(self, attr):
        try:
            getattr(self.fooInstances[0], attr)
        except AttributeError:
            raise AttributeError(f"'Bar' object has no attribute '{attr}'")
        else:
            def foo_wrapper(*args, **kwargs):
                for foo_inst in self.fooInstances:
                    getattr(foo_inst, attr)(*args, **kwargs)
            return foo_wrapper 

__getattr__Bar如果对Bar对象的属性查找失败,则调用 on 。然后我们尝试查看一个Foo实例是否具有该属性;如果没有,则提出一个,AttributeError因为既不Bar也不Foo接受该属性。但是,如果Foo确实有它,我们将返回一个函数,该函数在调用时会在驻留在object 中的attr每个瞬间调用方法 ( ) 。FooBar

用法:

     ...
     # changed this method in Foo to see the passing-an-argument case
     def addOneToA(self, val):
         self.a += 1
         print(f"val = {val}")
     ...


>>> bar = Bar([Foo(), Foo(), Foo()])

>>> bar.addOneToB()
>>> [foo.b for foo in bar.fooInstances]
[1, 1, 1]

>>> bar.addOneToA(val=87)  # could also pass this positionally
val = 87
val = 87
val = 87

>>> bar.this_and_that
AttributeError: 'Bar' object has no attribute 'this_and_that'


以上是将多个类方法应用于对象列表的Pythonic方式的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>