是否有可能重写Python中的namedtuple方法?

问题描述:

比方说,我有一个这样的类:是否有可能重写Python中的namedtuple方法?

class Foo(namedtuple('Foo', ['f1'])): 
    def f1(self): 
     print('Default f1') 

    def __new__(cls, f1=f1): 
     return super().__new__(cls, f1) 

而且让我们说我以后上创建一个Foo对象,然后选择要覆盖的方法定义,对于F1,就像这样:

def my_f1(): 
    print("My f1") 

foo = Foo(f1=my_f1) 

如果我然后尝试:

foo.f1() 

我得到:

Default f1 

我试图让“我的f1”打印,当然。我也希望f1是可选的。这里发生了什么?是否可以为namedtuple中的方法定义默认实现,然后在新的中覆盖它?

+1

在我看来,你想用一个字段的默认值namedtuple。在这种情况下,默认值是可调用的,但它没有太大的区别:http://*.com/questions/11351032/named-tuple-and-optional-keyword-arguments –

+0

@AndreaCorbellini:它使一个巨大的差异,因为处理属性的属性被方法破坏了。 –

+0

@MartijnPieters:只有当你想在'class Foo'中声明'f1'时,它才会有所不同。但是这太过复杂(详情请参阅你自己的答案:P)。在Foo类外声明'f1'并将其设置为默认参数使事情变得更容易。 –

您不能同时使用同一名称的方法和插槽。被命名的元组使用slots,并且这些被实现为property对象与方法在相同的命名空间中。通过定义一个方法f1你打一顿的f1属性:

>>> from collections import namedtuple 
>>> namedtuple('Foo', ['f1']).f1 
<property object at 0x1069764c8> 
>>> class Foo(namedtuple('Foo', ['f1'])): 
...  def f1(self): 
...   print('Default f1') 
... 
>>> Foo.f1 
<unbound method Foo.f1> 

property对象只返回self[0]。所以,无论是位置访问f1值:

class Foo(namedtuple('Foo', ['f1'])): 
    def f1(self): 
     if self[0]: 
      return self[0]() 
     print('Default f1') 

或给你的属性不同名,并有f1方法委托到:

class Foo(namedtuple('Foo', ['f1_callable'])): 
    def f1(self): 
     if self.f1_callable: 
      return self.f1_callable() 
     print('Default f1') 

演示:

>>> def my_f1(): 
...  print("My f1") 
... 
>>> class Foo(namedtuple('Foo', ['f1'])): 
...  def f1(self): 
...   if self[0]: 
...    return self[0]() 
...   print('Default f1') 
... 
>>> foo = Foo(my_f1) 
>>> foo.f1() 
My f1 
>>> foo = Foo(None) 
>>> foo.f1() 
Default f1 

避免在class Foo内声明f1。相反,在模块级声明它,并把它作为一个default argument for your namedtuple

def f1(): 
    print('Default f1') 

Foo = namedtuple('Foo', 'f1') 
Foo.__new__.__defaults__ = (f1,) 

用法:

>>> foo = Foo() 
>>> foo.f1() 
Default f1 

>>> def other_f1(): 
...  print('Another f1') 
>>> foo = Foo(f1=other_f1) 
>>> foo.f1() 
Another f1