4

我正在转换旧的 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__,其他方法被替换得很好。

4

2 回答 2

3

这记录在 python 数据模型中的特殊方法名称下。具体来说:

例如,如果一个类定义了一个名为 的方法__getitem__,并且 x 是该类的一个实例,那么对于旧式类和新式类x[i]大致等价。x.__getitem__(i)type(x).__getitem__(x, i)

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

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()')

对我来说(python2.7.3,OS-X 10.5.8),new-style class 快了将近 4 倍!

2.27801704407
0.602614879608
于 2013-04-17T14:25:25.223 回答
3

这有效:

NewStyle.__str__ = lambda self: 'modified'

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

于 2013-04-17T14:15:38.887 回答