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