在新式类中替换__str__

时间:2013-04-17 14:07:13

标签: python python-2.7

我正在转换旧的Python代码并用新的样式类替换了一些类。问题是这打破了替换__str__的行为,我不明白为什么。

class OldStyle():
    def __str__(self):
        return 'original'

old = OldStyle()
print old
old.__str__ = lambda: 'modified'
print old


class NewStyle(object):
    def __str__(self):
        return 'original'

new = NewStyle()
print new
new.__str__ = lambda: 'modified'
print new

我期待

original
modified
original
modified

但我得到了

original
modified
original
original

也就是说,__str__未在新样式中正确替换。打印new.__str__会正确返回新的lambda,但str(new)仍然不会调用它。我认为这是一些方法查找缓存问题,但即使之前从未打印过对象,也会发生这种情况。

为什么会这样?我从来没有听说过这种行为差异,它只发生在__str__,其他方法被替换得很好。

2 个答案:

答案 0 :(得分:3)

这有效:

NewStyle.__str__ = lambda self: 'modified'

我们看到的似乎是__str__方法现在与类类型绑定,而不是实例。我不知道为什么会这样。您可以明确调用new.__str__()并获取替换后的方法,但str(new)始终会调用NewStyle.__str__(new)

答案 1 :(得分:3)

这在special method names下的python数据模型中有记录。具体做法是:

  

例如,如果一个类定义了一个名为__getitem__的方法,并且x是该类的一个实例,那么x[i]大致相当于旧式类的x.__getitem__(i)和{ {1}}用于新式课程。

我相信这允许新式类在这些操作方面更有效率,因为对于旧样式类,python被迫查找属性然后使用新式类调用属性, python可以只引用它作为C结构的一部分,有效地将查找和调用推送到本机C代码。例如:

type(x).__getitem__(x, i)

对我来说(python2.7.3,OS-X 10.5.8),新式课程的速度快了近4倍!

class Foo:
    def __add__(self,other):
        return 4 + other

class Bar(object):
    def __add__(self,other):
        return 4 + other

import timeit
print timeit.timeit('f + 5','from __main__ import Foo; f = Foo()')
print timeit.timeit('b + 5','from __main__ import Bar; b = Bar()')