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

时间:2016-01-25 14:27:30

标签: python class methods metaprogramming

我有一个类,我想为列表的每个元素初始化属性self.listNadd_to_listN方法,例如来自attrs = ['list1', 'list2']我想要list1list2初始化为空列表,并创建方法add_to_list1add_to_list2。每个add_to_listN方法应采用两个参数,例如valueunit,并将元组(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))

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

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

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

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

更新

尽管Benjamin Hodgson提出some good points,但我并不是要求(也许是更好的)替代方法来做到这一点,而是为了使用我提到的工具的最佳方式。我正在使用一个简化的例子,以便不关注细节。

为了进一步澄清我的问题:add_to_listN方法应该是附加,而不是替换setter / getters(所以我仍然希望能够l1 = f.list1f.list1 = []f = Foo())。

1 个答案:

答案 0 :(得分:2)

您正在设计错误。您可以覆盖__getattr__,解析属性名称,并返回一个符合您需要的闭包,但动态生成方法很奇怪,奇怪的代码是错误的代码。通常情况下你需要这样做,但这不是其中之一。

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

class Foo:
    def __init__(self):
        self.lists = [
            [],
            []
        ]
    def add(self, row, value):
        self.lists[row].append(value)

然后foo.add1(x)变为foo.add(1, x); foo.add2(x)变为foo.add(2, x),依此类推。有一种方法,沿着变化轴参数化,适用于所有情况 - 而不是一连串的临时生成方法。它简单得多。

Don't mix up the data in your system with the names of the data in your system