是否可以创建一个从namedtuple的多个实例继承的类,或者创建具有相同效果的类(具有将基本类型的字段组合在一起的不可变类型)?我还没有找到一种方法。

此示例说明了该问题:

>>> class Test(namedtuple('One', 'foo'), namedtuple('Two', 'bar')):
>>>    pass

>>> t = Test(1, 2)
TypeError: __new__() takes 2 positional arguments but 3 were given

>>> t = Test(1)
>>> t.foo
1
>>> t.bar
1


问题似乎是namedtuple不使用super初始化其基类,这在创建一个基类时可以看到:

>>> namedtuple('Test', ('field'), verbose=True)
[...]
class Test(tuple):
[...]
    def __new__(_cls, field,):
        'Create new instance of Test(field,)'
        return _tuple.__new__(_cls, (field,))


即使我考虑编写自己的namedtuple版本来解决此问题,也不是很清楚如何做到这一点。如果一个类的MRO中有多个namedtuple实例,则它们必须共享基类tuple的单个实例。为此,他们必须协调哪个namedtuple在基本元组中使用哪个索引范围。

有没有更简单的方法可以通过namedtuple或类似方法实现多重继承?有没有人在某个地方实现过?

最佳答案

您可以使用装饰器或元类将父命名元组字段组合为新的命名元组,并将其添加到类__bases__中:

from collections import namedtuple

def merge_fields(cls):
    name = cls.__name__
    bases = cls.__bases__

    fields = []
    for c in bases:
        if not hasattr(c, '_fields'):
            continue
        fields.extend(f for f in c._fields if f not in fields)

    if len(fields) == 0:
        return cls

    combined_tuple = namedtuple('%sCombinedNamedTuple' % name, fields)
    return type(name, (combined_tuple,) + bases, dict(cls.__dict__))


class SomeParent(namedtuple('Two', 'bar')):

    def some_parent_meth(self):
        return 'method from SomeParent'


class SomeOtherParent(object):

    def __init__(self, *args, **kw):
        print 'called from SomeOtherParent.__init__ with', args, kw

    def some_other_parent_meth(self):
        return 'method from SomeOtherParent'


@merge_fields
class Test(namedtuple('One', 'foo'), SomeParent, SomeOtherParent):

    def some_method(self):
        return 'do something with %s' % (self,)


print Test.__bases__
# (
#   <class '__main__.TestCombinedNamedTuple'>, <class '__main__.One'>,
#   <class '__main__.SomeParent'>, <class '__main__.SomeOtherParent'>
# )
t = Test(1, 2)  # called from SomeOtherParent.__init__ with (1, 2) {}
print t  # Test(foo=1, bar=2)
print t.some_method()  # do something with Test(foo=1, bar=2)
print t.some_parent_meth()  # method from SomeParent
print t.some_other_parent_meth()  # method from SomeOtherParent

关于python - 如何在多重继承中使用namedtuple,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28941108/

10-12 18:32