2015-01-07 2 views
1

나는 super()의 작동 방식을 이해하려고합니다. 나는 그것이 무엇을하는지 이해하지만 나는 뒤에서 무슨 일이 벌어지는 지에 대한 메커니즘을 이해하지 못합니다.super()가 메소드의 처음이나 끝에서 호출되는 것과 다른 점은 무엇입니까?

class b(a): 
    def __init__(self, name, age): 
     self.name=name 
     self.age=age 
     super(b, self).__init__(name, age) 

과 : 내가 정확히 이해하지 못하는 한 가지의 차이점은 어쩌면이 두 가지 예에서 차이가 없습니다

class b(a): 
    def __init__(self, name, age): 
     super(b, self).__init__(name, age) 
     self.name=name 
     self.age=age 

을,하지만 난 다른 상황이 알고 곳의 위치 super() 중요합니다. 예를 들어, 장고에 대한 도움이 필요했던이 장고 메서드는 아래쪽이 아닌 if 문 위로 super()을 이동하라는 지시를 받았습니다. 왜 이것이 중요한지 알고 싶습니다.

class Mymodel(models.Model): 
    photo = models.ImageField(upload_to="...", blank=True) 

def save(self, *args, **kwargs): 
    image_resized = kwargs.pop('image_resized',False) 
    super(Mymodel, self).save(*args, **kwargs) 
    if self.photo and image_resized: 
     basewidth = 300 
     filename = self.get_source_filename() 
       image = Image.open(filename) 
     wpercent = (basewidth/float(image.size[0])) 
     hsize = int((float(image.size[1])*float(wpercent))) 
     img = image.resize((basewidth,hsize), PIL.Image.ANTIALIAS) 
     self.photo = img 
     self.save(image_resized = True) 
+3

생각해보십시오. 당신의 코드가 슈퍼 클래스'__init__'에서만 초기화되는 인스턴스 속성에 의존한다면 어떻게 될까요? 일찍 전화하면할수록 좋습니다. 또한 '슈퍼'입니다. – jonrsharpe

+0

마지막으로 호출하고 싶은 상황이 있습니다. 보통'__new__'에서와 같습니다. –

+2

** 단지 부모 클래스에서 찾을 수있는 메소드 인 ** 일 뿐이지 만 ** 메소드 호출 **입니다. 그러나 * 당신이 그것을 부를 때 다른 어떤 방법을 부르는 것과 같은 영향을 미친다. 물건이 생겼어. 전화하지 않으면 그 일은 일어나지 않습니다. –

답변

6

클래스 b (있는 경우)의 두 버전 간의 차이점은 수퍼 클래스 (a)의 기능에 전적으로 달려 있습니다. 그냥 단순하고 선명 예를 보자 :

class a(object): 
    def __init__(self): 
     self.foo = 23 

class b1(a): 
    def __init__(self, name, age): 
     self.foo = 42 
     super(b, self).__init__() 

class b2(a): 
    def __init__(self, name, age): 
     super(b, self).__init__() 
     self.foo = 42 

클래스 b1 첫 세트 foo 42를 - (실제로는) 다음 self.foo이 후 23 가치가 될 수있을 테니까요, 그래서 23에 동일한 속성을 재설정하는 a.__init__를 호출 b1.__init__. foo (23)에 설정 b2 첫 번째 (실제로는) a.__init__를 호출

클래스, - 다음, 그것은 그래서 42 같은 속성을 다시 진행 self.foob2.__init__ 후 42 가치가 될 수있을 테니까요.

이 사례는 동일한 값에 대해 서로 다른 값을 할당하기 때문에 더 간단하고 명확합니다. 따라서 두 번째 할당이 첫 번째 할당의 효과를 재정의하는 것은 매우 직관적입니다. 따라서 서브 클래스가 자신의 일을 수행하기 전에 수퍼 클래스의 __init__을 호출하면 서브 클래스가 수퍼 클래스에서 수행 된 설정의 일부 또는 전부를 대체하게됩니다. 그 후에 그것을 부르는 것은 그 반대를 의미합니다.

self 속성에 대한 단순한 할당보다 조금 더 미묘한 초기화 작업에는 똑같은 추론이 적용됩니다. 즉, 어떤 클래스, 하위 또는 수퍼 유저가 다른 클래스에서 수행 한 작업을 조정하거나 덮어 쓰게되는 것입니다 (많은 두 가지 초기화가 전혀 중요하지 않음).

OOP에서는 서브 클래스가 수퍼 클래스를 "오버라이드"하는 것이 훨씬 더 일반적입니다. 결과적으로 수퍼 클래스의 __init__을 호출하는 정상적인 시간은 서브 클래스의 시작 부분에 있습니다. 이는 더 관용적입니다. subtler 효과가 필요할 때, 나중에 수퍼 클래스의 __init__을 호출해도 좋지만, "약간 변칙적 인"경우에는 일반적으로 코드 독자가 수행중인 작업과 이유를 설명하는 데 도움이됩니다.

+0

매우 도움이됩니다. 고맙습니다! – stephan

1

super().__init__()은 "이"(평 또는 자기)로부터 상속 클래스의 생성자를 실행합니다. 따라서 상속 된 변수 나 상속받은 클래스의 생성자에서 사용해야하는 변수를 수정하는 작업이 있으면 먼저 호출해야합니다. 그렇지 않으면 아직 불필요한만큼 호출됩니다. 항상 생성자가 시작될 때 항상 호출하는 것이 가장 좋습니다. 그래도 호출되는 위치를 항상 알 수 있습니다 (필요한 경우).

+2

'super' 자체는 아무 것도 실행하지 않고, 부모 클래스에서 어떤 메소드가 실행될 지 현재 인스턴스 만 리턴합니다. – Kroltan

+1

죄송합니다. 필자가 파이썬을 사용하기 시작한 지 오래지만, 여전히 도움을주고 싶었습니다. 파이썬 언어를 더 잘 반영하도록 편집했습니다. – Theyouthis

+0

문제가되지 않습니다. 나는 기분을 상하게하려하지 않았습니다. 그냥 사람들이 길을 혼란스러워하지 않도록 지적합니다. ("하지만 스택 오버플로가 슈퍼가 생성자를 실행한다고 대답했습니다."). 내 영어가 완벽하지 않으며, 종종 내가 의도하지 않게 가혹한 것처럼 들릴 수도 있습니다. 죄송합니다. – Kroltan

관련 문제