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

时间:2015-09-25 15:18:29

标签: python override 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中的方法定义默认实现,然后在 new 中覆盖它?

2 个答案:

答案 0 :(得分:5)

您不能同时使用相同名称的方法和插槽。命名元组使用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

答案 1 :(得分:0)

避免在f1内声明class Foo。相反,在模块级别声明它,并将其用作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