2013-10-26 2 views
125

super()는 인수없이 호출 할 수 있습니다 :이 작업을하기 위해왜 Python 3.x의 super() 매직입니까? 파이썬 3.x의에서

class A(object): 
    def x(self): 
     print("Hey now") 

class B(A): 
    def x(self): 
     super().x() 
>>> B().x() 
Hey now 

가 일부 컴파일시의 마법이 수행, 하나 개 결과 어느 것을 다음 코드 (이는 supersuper_에 리 바인드) 실패

super_ = super 

class A(object): 
    def x(self): 
     print("No flipping") 

class B(A): 
    def x(self): 
     super_().x() 
>>> B().x() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in x 
RuntimeError: super(): __class__ cell not found 

왜 입술에 super() 수없는 컴파일러의 도움없이 런타임시 수퍼 클래스를 olve 하시겠습니까? 이 행동 또는 그 근본적인 이유가 부주의 한 프로그래머를 물릴 수있는 실제적인 상황이 있습니까?

... 그리고 부차적 인 질문으로 파이썬에서 다른 이름으로 리바 인딩하여 기능을 손상시킬 수있는 다른 예제가 있습니까?

+6

내가 아르 민을 할거야 (이 [한]에 설명을 http://lucumr.pocoo.org/2010/1/7/pros-and-cons-about-python-3 /)을 사용합니다. 이것은 또 다른 좋은 [게시물] (http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/) –

+0

관련 : http://stackoverflow.com/q/36993577/674039 – wim

답변

184

새로운 마법 super() 동작이 추가되어 D.R.Y를 위반하지 않도록했습니다. (자신을 반복하지 마십시오) 원칙은 PEP 3135을 참조하십시오.

class Foo(Bar): 
    def baz(self): 
     return super(Foo, self).baz() + 42 

Spam = Foo 
Foo = something_else() 

Spam().baz() # liable to blow up 

같은이 리 바인드하는 데코레이터는 새로운 객체를 돌려줍니다 데코레이터를 사용하여 적용을 명시 적으로 글로벌로 참조하여 클래스 이름을 갖는 것은 또한 super() 자체 발견 같은 리 바인딩 문제에 대한 경향이있다 클래스 이름 : 마법 super()__class__ 세포가 원래의 클래스 객체에 대한 액세스를 제공하여 친절하게 이러한 문제를 비켜

@class_decorator_returning_new_class 
class Foo(Bar): 
    def baz(self): 
     # Now `Foo` is a *different class* 
     return super(Foo, self).baz() + 42 

.

PEP는 Guido (누가 initially envisioned super becoming a keyword)에 의해 시작되었으며 셀을 사용하여 현재 클래스 was also his을 검색한다는 아이디어가있었습니다. 물론 키워드로 만드는 아이디어는 first draft of the PEP의 일부였습니다.

그러나 사실 Guido 자신이 stepped away from the keyword idea as 'too magical'인데, 대신 현재 구현을 제안합니다. 그는 anticipated that using a different name for super() could be a problem :

내 패치는 중간 솔루션을 사용 : 그것은 당신이 'super'라는 이름의 변수를 사용할 때마다 __class__ 을 필요로 가정합니다. 따라서, 당신은 (세계적으로) suppersuper 이름을 변경하고 supper하지만 super, 그것은 인수없이 작동하지 않습니다 사용 (하지만 당신이 그것을 통과하면 그것은 여전히 ​​작동 중 __class__ 또는 실제 클래스 객체) 경우; 관련이없는 변수의 이름이 super 인 경우 문제가 발생하지만이 방법은 셀 변수에 사용되는 호출 경로가 약간 느린 입니다.

그래서, 결국, 그것은 super 키워드를 사용하는 느낌이 좋지 않았다, 그리고 마법 __class__ 셀을 제공하는 것이 허용 타협 것을 선포 귀도 자신했다.

구현의 암시 적 동작은 다소 놀랍지 만, super()은 언어에서 잘못 적용된 기능 중 하나입니다. 인터넷에서 오용 된 모든 super(type(self), self) 또는 super(self.__class__, self) 호출을 살펴보십시오. 이 코드 중 하나라도 파생 클래스 you'd end up with an infinite recursion exception에서 호출 된 경우 적어도 super() 호출을 인수없이 사용하면 문제를 피할 수 있습니다.

이름이 바뀌면 super_; 귀하의 방법 에서 __class__을 참조 하시어으로 다시 보내 주시면 다시 작동합니다. 당신이 당신의 방법에 super또는__class__ 이름을 참조하거나하면 세포가 생성됩니다

>>> super_ = super 
>>> class A(object): 
...  def x(self): 
...   print("No flipping") 
... 
>>> class B(A): 
...  def x(self): 
...   __class__ # just referencing it is enough 
...   super_().x() 
... 
>>> B().x() 
No flipping 
+1

좋은 글쓰기. 그러나 여전히 진흙처럼 분명합니다. 당신은 super()가'self.super();와 같은'def super (of_class = magic __class __)'와 같은 자동으로 인스턴스화 된 함수와 동일하다는 것을 말하고 있습니다. def 슈퍼 (자기) : return self .__ class__'? –

+12

@CharlesMerriam :이 글은 인수가없는'super()'가 어떻게 작동하는지에 관한 것이 아닙니다; 그것은 주로 * 왜 * 존재 하는지를 다룹니다. 클래스 메소드의'super()'는 컴파일시에'ReferenceToClassMethodIsBeingDefinedIn'이 결정되고'__class__'라는 클로저로 메소드에 첨부 된'super (ReferenceToClassMethodIsBeingDefinedIn, self)'와 같고' '는 실행시 호출 프레임에서 둘다 찾아 볼 것입니다. 그러나 실제로이 모든 것을 알 필요는 없습니다. –

+1

@CharlesMerriam :하지만'super()'는 자동으로 인스턴스화 된 함수가 될 수 없습니다. *, no. –