2013-04-17 2 views
4

이전 파이썬 코드를 변환하고 일부 클래스를 새 스타일 클래스로 바꿨습니다. 문제는 이것이 __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 

을 예상하지만, __str__ 올바르게 새로운 스타일로 대체되지 않은됩니다
original 
modified 
original 
original 

을 얻었다. new.__str__은 새 람다를 올바르게 반환하지만 str(new)은 여전히이 람다를 호출하지 않습니다. 나는 이것이 어떤 메소드 룩업 캐싱 문제라고 생각했지만, 객체가 이전에 결코 인쇄되지 않았더라도 이런 일이 발생한다.

왜 이런 일이 발생합니까? 나는이 동작의 차이에 대해 들어 본 적이 없으며 __str__에서만 발생하며 다른 메서드는 잘 대체됩니다.

+0

마지막 수정을'NewStyle .__ str__ = lambda self : 'modified''로 바꾸는 것은 예상대로 작동합니다. 나는 이전과 새로운 스타일의 클래스에서 메소드 해석 순서가 다르다고 생각한다. –

+0

흥미 롭습니다. 문제는 그 단일 인스턴스에서만'__str__'을 대체해야한다는 것입니다. 나는 그것을 다른 방식으로 구현할 수 있다고 생각하지만 호기심이 생겼다. – BoppreH

+1

호기심에서, 처음에 인스턴스에서'__str__' 코드를 대체하는 이유는 무엇입니까? 소리 ... 못 생겼어. – geoffspear

답변

3

이 내용은 special method names 아래의 python 데이터 모델에 설명되어 있습니다. 특히 : 클래스가 __getitem__라는 방법을 정의하고, x는이 클래스의 인스턴스의 경우는

는 예를 들어, x[i] 새로운 스타일의 클래스에 대한 이전 스타일의 클래스 x.__getitem__(i)type(x).__getitem__(x, i) 거의 비슷하다.

필자는 이전 스타일 클래스에서는 python이 속성을 찾아서 new-style 속성을 사용하도록 강요했기 때문에 새로운 스타일 클래스가이 작업의 측면에서 좀 더 효율적이라는 것을 믿습니다. 파이썬은 단순히 C 구조체의 일부로서이를 참조하여 어딘가에 실제로 네이티브 C 코드로 룩업과 호출을 푸시 할 수있다. 예를 들면 : 거의 4 배 빠른 날 (python2.7.3, OS-X 10.5.8), 새로운 스타일의 클래스가 들어

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

!

2.27801704407 
0.602614879608 
3

이 작동 : 그것은 것 같다

NewStyle.__str__ = lambda self: 'modified' 

우리가보고있는 것은 __str__ 방법이 아니라 인스턴스보다, 이제 클래스 유형에 연결되어 있다는 점이다. 왜 그런지 모르겠습니다. new.__str__()을 명시 적으로 호출하여 대체 된 메소드를 얻을 수 있지만 str(new)은 항상 NewStyle.__str__(new)을 호출합니다.

+0

하지만 모든 NewStyle 인스턴스의 동작이 변경됩니다. – BoppreH

+0

물론 그렇습니다.어쩌면 파생 클래스를 만들어서 다른 to-string 비헤이비어가 필요한 한 인스턴스에 대해 인스턴스화해야합니다. –