Python - 在类中动态添加方法的推荐方法

nic*_*ick 6 python methods metaprogramming class

我有一个类,我想为列表的每个元素初始化一个属性self.listN和一个add_to_listN方法,例如从attrs = ['list1', 'list2']我想要list1并list2初始化为空列表和方法add_to_list1以及add_to_list2要创建的方法.每个add_to_listN方法应该采用两个参数,比如说value和unit,并将一个元组附加(value, unit)到相应的参数listN.

因此,该类最终应该是这样的:

class Foo():
    def __init__(self):
        self.list1 = []
        self.list1 = []

    def add_to_list1(value, unit):
        self.list1.append((value, unit))

    def add_to_list2(value, unit):
        self.list2.append((value, unit))
Run Code Online (Sandbox Code Playgroud)

撇开所有支票和课堂上的其他人,我想出了这个:

class Foo():
    def __init__(self):
        for attr in ['list1', 'list2']:
            setattr(self, attr, [])
            setattr(self, 'add_to_%s' % attr, self._simple_add(attr))

    def _simple_add(self, attr):
        def method(value, unit=None):
            getattr(self, attr).append((value, unit))
        return method
Run Code Online (Sandbox Code Playgroud)

我还检查了其他解决方案,例如这里建议的解决方案,我想"正确",所以我的问题是:

  • 这些方法(是)实际上是否应该classmethod?
  • 创建方法是否有成本__init__,在这种情况下是否有替代方案?
  • 运行for循环并添加这些方法的最佳位置在哪里?在类定义中?出来的?
  • 在这种情况下是否推荐使用元类?

更新

虽然Benjamin Hodgson提出了一些好处,但我并不是要求一种(或许更好的)替代方法来做到这一点,而是为了使用我提到的工具的最佳方式.我正在使用一个简化的例子,以便不关注细节.

为了进一步澄清我的问题:这些add_to_listN方法是额外的,而不是取代setter/getters(所以我仍然希望能够做到l1 = f.list1和f.list1 = []使用f = Foo()).

Ben*_*son 2

你犯了一个设计错误。您可以重写__getattr__、解析属性名称,并返回一个执行您想要的操作的闭包,但是动态生成方法很奇怪,奇怪的代码就是糟糕的代码。经常有一些情况需要您这样做,但这不是其中之一。

与其生成对n其中一个n对象执行相同操作的方法,为什么不只编写一个由 参数化的方法呢n?大致是这样的:

class Foo:
    def __init__(self):
        self.lists = [
            [],
            []
        ]
    def add(self, row, value):
        self.lists[row].append(value)
Run Code Online (Sandbox Code Playgroud)

那么就foo.add1(x)变得简单foo.add(1, x);foo.add2(x)变为foo.add(2, x),等等。有一种方法,沿着变化轴参数化,适用于所有情况 - 而不是一长串临时生成的方法。简单多了。

不要将系统中的数据与系统中的数据名称混淆。