2012-06-16 4 views
4

나는 다음과 같은 예는 약간 놀라운 발견 : 파이썬 방법 조회 규칙은

>>> class Foo: 
     def blah(self): 
      pass 


>>> f = Foo() 
>>> def bar(self): 
     pass 

>>> Foo.bar = bar 
>>> f.bar 
<bound method Foo.bar of <__main__.Foo object at 0x02D18FB0>> 

나는 바인딩 방법은 각각의 특정 인스턴스와 관련된 것으로, 건설에 그것을 배치 할 것으로 예상.

는 그러나 과정에 대한 이해가 명확하게 결함이
>>> g = Foo() 
>>> g.blah is f.blah 
False 

: 참, 그리고 - 기본 기능에 전달하는 예를 알 수 있도록 바운드 방법은, 각 인스턴스에 대해 다르게해야한다는 것을 논리적 보인다 왜냐하면 클래스 속성에 함수를 할당하면 이 이미 다음에 의해 생성 된 인스턴스에 넣을 것이라고 기대할 수 없기 때문입니다..

  1. 왜 인스턴스에 소급 적용 클래스에 기능을 할당 않습니다 -

    그래서, 내 질문은 두 배입니다? 이를 실제로 만드는 실제 조회 규칙 및 프로세스는 무엇입니까?

  2. 언어에 의해 보증되는 것이 있습니까? 아니면 일어나는 일입니까?
  3. 당신은 당신의 마음을 날려 할

답변

11

,이 시도 : 맞아

f.blah is f.blah 

는 인스턴스 메소드 래퍼는 다른 당신이 그것을 액세스 할 때마다입니다.

사실 인스턴스 메서드는 설명자입니다. 즉, f.blah는 실제로 :

Foo.blah.__get__(f, type(f)) 

방법 실제로 인스턴스에 저장되지 않습니다; 그것들은 클래스에 저장되고 메서드 래퍼 (method wrapper)가 즉시 생성되어 메서드를 인스턴스에 바인딩합니다.

+0

아, 맞습니다.나는 깨닫지 못했거나 인스턴스를'__get__ '에 전달한 디스크립터 프로토콜을 잊었다. 그게 저에게 모든 관련 문서를 읽도록 가르쳐 줄 것입니다. :-) – lvc

+0

cf http://wiki.python.org/moin/FromFunctionToMethod에 대한 자세한 내용은 여기를 참조하십시오. –

7

인스턴스에 메서드가 "포함되어 있지 않습니다. 조회 프로세스는 foo.bar에 액세스 할 때 동적으로 발생합니다. 인스턴스에 해당 이름의 속성이 있는지 확인합니다. 그것이 아니기 때문에, 그것은 클래스를 쳐다 본다. 그러면 그 클래스가 그 클래스에 가지고있는 어떤 속성이든 찾는다. 이러한 점에서 메소드는 특별하지 않습니다. Foo.bar = 2을 설정하면 동일한 효과가 나타납니다. 그 후 foo.bar은 2로 평가됩니다.

속성 검색은이 방식으로 진행됩니다. 즉, 먼저 인스턴스, 인스턴스에 속성이없는 경우 클래스가 진행됩니다. (조회 규칙은 special methods implicitly invoked via operator overloading, etc.과 다릅니다.)

속성을 인스턴스에 직접 지정하는 경우에만 클래스 속성이 마스크됩니다.

>>> foo = Foo() 
>>> foo.bar 
Traceback (most recent call last): 
    File "<pyshell#79>", line 1, in <module> 
    foo.bar 
AttributeError: 'Foo' object has no attribute 'bar' 
>>> foo.bar = 2 
>>> Foo.bar = 88 
>>> foo.bar 
2 

위의 내용은 모두 바운드/언 바운드 방식과 별개입니다. 파이썬의 클래스 메카니즘은 을 사용하기 때문에 foo.bar에 액세스하면 새로운 바운드 메소드 인스턴스가 즉석에서 작성됩니다. 그렇기 때문에 서로 다른 객체에 다른 바인딩 된 메소드 인스턴스가 표시됩니다. 그러나 기본적으로 이러한 바인딩 된 메서드는 클래스에 작성한 메서드에 정의 된대로 동일한 코드 개체에 의존합니다.

>>> foo = Foo() 
>>> foo2 = Foo() 
>>> foo.blah.im_func.__code__ is foo2.blah.im_func.__code__ 
True