如何在多重继承中使用namedtuples [英] How to use namedtuples in multiple inheritance
问题描述
是否可以创建一个继承自 namedtuple
,或创建具有相同效果的东西(具有组合基本类型字段的不可变类型)?我还没有找到办法。
Is it possible to create a class that inherits from multiple instances of namedtuple
, or create something to the same effect (having an immutable type that combines the fields of the base types)? I haven't found a way to do so.
此示例说明了问题:
>>> 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
初始化其基类,如创建一个基类时所见:
The problem seems to be that namedtuple
does not use super
to initialize its base class, as can be seen when creating one:
>>> 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
的实例,则它们必须共享基类的单个实例元组
。要做到这一点,他们必须协调哪个 namedtuple
使用基本元组中的哪个索引范围。
Even if I considered writing my own version of namedtuple
to fix this, it is not obvious how to do that. If there are multiple instances of namedtuple
in the MRO of a class they'd have to share a single instance of the base class tuple
. To do that, they'd have to coordinate on which namedtuple
uses which range of indices in the base tuple.
使用 namedtuple
或类似的东西,有没有更简单的方法来实现多重继承?有人已经在某处实现了吗?
Is there any simpler way to achieve multiple inheritance with a namedtuple
or something similar? Has anyone already implemented that somewhere?
推荐答案
您可以使用装饰器或元类将父命名的元组字段组合成新的命名元组并将其添加到类 __ bases __
:
You could use a decorator or metaclass to combined the parent named tuple fields into a new named tuple and add it to the class __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
这篇关于如何在多重继承中使用namedtuples的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!