2013-04-17 28 views
4

我正在轉換舊的Python代碼並用新風格類替換某些類。問題是,這打破了替換__str__的行爲,我不知道爲什麼。替換新風格類中的__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

用'NewStyle .__ str__ = lambda self:'modified''替換上次修改可按預期工作。我認爲舊式和新式課程的方法解析順序是不同的。 – 2013-04-17 14:11:27

+0

有趣。問題是我只需要在單個實例中替換'__str__'。我想我可以用另一種方式來實施,但我很好奇。 – BoppreH

+1

出於好奇,爲什麼你的代碼首先在實例上代替了'__str__'?聽起來很醜陋。 – geoffspear

回答

3

這是在special method names下的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),新風格的類是快了近4倍!

2.27801704407 
0.602614879608 
3

這工作:

NewStyle.__str__ = lambda self: 'modified' 

好像就是我們所看到的是,該__str__方法是聯繫在一起的類類型現在,而不是實例。我不確定這是爲什麼。您可以明確地致電new.__str__()並獲取替換的方法,但str(new)始終調用NewStyle.__str__(new)

+0

但是這改變了所有'NewStyle'實例的行爲。 – BoppreH

+0

當然是的。也許你應該創建一個派生類併爲你想要一個不同的字符串行爲的實例實例化它。 –