是否可以在Python中覆盖namedtuple中的方法?

Lat*_*der 2 python overriding namedtuple

假设我有这样一个类:

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

    def __new__(cls, f1=f1):
        return super().__new__(cls, f1)
Run Code Online (Sandbox Code Playgroud)

让我们说我稍后创建一个Foo对象并选择覆盖f1的方法定义,如下所示:

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

foo = Foo(f1=my_f1)
Run Code Online (Sandbox Code Playgroud)

如果我然后尝试:

foo.f1()
Run Code Online (Sandbox Code Playgroud)

我明白了:

Default f1
Run Code Online (Sandbox Code Playgroud)

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

Mar*_*ers 5

您不能同时使用相同名称的方法和插槽.命名元组使用插槽,这些插槽在与方法相同的命名空间中实现为property对象.通过定义一个方法来破坏属性:f1f1

>>> 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>
Run Code Online (Sandbox Code Playgroud)

property对象只是返回self[0].所以要么f1按位置访问值:

class Foo(namedtuple('Foo', ['f1'])):
    def f1(self):
        if self[0]:
            return self[0]()
        print('Default f1')
Run Code Online (Sandbox Code Playgroud)

或者为您的属性指定一个不同的名称,并让f1方法委托给它:

class Foo(namedtuple('Foo', ['f1_callable'])):
    def f1(self):
        if self.f1_callable:
            return self.f1_callable()
        print('Default f1')
Run Code Online (Sandbox Code Playgroud)

演示:

>>> 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
Run Code Online (Sandbox Code Playgroud)