2009-04-30 9 views
389

Python에서 간단한 객체 계층 구조를 만들 때 파생 클래스에서 부모 클래스의 메소드를 호출 할 수 있기를 바랍니다. Perl과 Java에는 this (super)에 대한 키워드가 있습니다. 펄, 나는이 작업을 수행 할 수 있습니다 파이썬에서Python에서 자식 클래스의 부모 클래스의 메서드를 호출 하시겠습니까?

package Foo; 

sub frotz { 
    return "Bamf"; 
} 

package Bar; 
@ISA = qw(Foo); 

sub frotz { 
    my $str = SUPER::frotz(); 
    return uc($str); 
} 

을, 내가 아이에서 명시 적으로 부모 클래스 이름을 가지고 나타납니다. 위의 예에서 Foo :: frotz()와 같은 작업을 수행해야합니다.

이 동작으로 인해 심층적 인 계층 구조를 만들기가 어렵 기 때문에이 방법이 적합하지 않습니다. 어떤 클래스가 상속 된 메서드를 정의했는지 알 필요가있는 경우 모든 종류의 정보 통증이 만들어집니다.

파이썬의 실제 제한 사항입니까, 제 이해의 차이입니까? 아니면 둘 다입니까?

+3

부모 클래스의 이름이 그렇게 나쁜 생각이 아니라고 생각합니다. 부모 클래스에 명시 적으로 이름을 지정했기 때문에 자식 클래스가 둘 이상의 부모를 상속하는 경우 도움이 될 수 있습니다. –

+6

클래스 이름을 지정하는 옵션은 좋지 않지만 반드시 그렇게해야한다는 것은 확실합니다. – johndodo

+0

파이썬 2와 파이썬 3 사이의 수퍼 핸들러의 변화를 알고 있어야합니다. [https://www.python.org/dev/peps/pep-3135/](https://www.python.org/dev/peps/ pep-3135 /). 수업 이름을 지정하는 것이 더 이상 필요하지 않습니다 (적어도 가끔은 신 아이디어 일지 모르지만). – jwpfox

답변

468

예 (단 new-style classes). super() 기능을 사용

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

"반환 Bar.baz (self, arg)"도 수행 할 수 있습니까? 그렇다면 어떤 것이 더 좋을까요? –

+8

예, 할 수 있습니다.하지만 OP는 호출 사이트 (이 경우 Bar)에서 명시 적으로 수퍼 클래스의 이름을 지정하지 않고이를 수행하는 방법을 묻고 있습니다. –

+6

super()는 다중 상속이 이상합니다. 그것은 "다음"클래스를 호출합니다. 이는 상위 클래스이거나 계층 구조의 다른 곳에 나타나는 완전히 관련없는 클래스 일 수 있습니다. –

80

파이썬은 또한뿐만 아니라 super이 있습니다

super(type[, object-or-type])

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.

예 :

class A(object):  # deriving from 'object' declares A as a 'new-style-class' 
    def foo(self): 
     print "foo" 

class B(A): 
    def foo(self): 
     super(B, self).foo() # calls 'A.foo()' 

myB = B() 
myB.foo() 
+4

오브젝트 기본 클래스와 함께 새로운 스타일의 클래스를 사용하여 시연했기 때문에 Adam보다 더 나은 예입니다. 새로운 스타일의 클래스에 대한 링크가 누락되었습니다. – Samuel

11

파이썬에서 슈퍼()도있다. 파이썬의 예전 스타일과 새로운 스타일의 클래스들 때문에 약간 불안해 보이지만 꽤 일반적으로 사용됩니다. 생성자 :

class Foo(Bar): 
    def __init__(self): 
     super(Foo, self).__init__() 
     self.baz = 5 
+1

나는 '슈퍼 (푸, 자기) .__ 초기화 __()' –

+0

죄송합니다 ... 실제로는 – lawrence

66
ImmediateParentClass.frotz(self) 

은 바로 위 부모 클래스 frotz 자체를 정의하거나 상속 여부, 잘 될 것입니다. super다중 상속의 적절한 지원을 위해서만 필요합니다 (모든 클래스가 올바르게 사용하는 경우에만 작동합니다). 일반적으로 AnyClass.whateverAnyClass이 정의하지 않았거나 무시하지 않으면 AnyClass의 조상에서 whatever을 조회 할 것이며 다른 모든 발생과 마찬가지로 "자식 클래스 호출 부모의 메서드"에 해당됩니다.

-21

이 좀 더 추상적 인 방법 :

super(self.__class__,self).baz(arg) 
+15

자기 .__ class__는 슈퍼와 함께 제대로 작동하지 않으므로 자기가 항상 인스턴스이고 그 __class__는 항상 인스턴스입니다. 수업. 즉, 클래스에서 super (self .__ class__ ..)를 사용하면 해당 클래스가 상속되고 더 이상 작동하지 않습니다. – xitrium

+16

강조하기 위해이 코드를 사용하지 마십시오. super()의 전체 목적을 상회합니다. 그것은 정확하게 MRO를 통과하는 것입니다. – Eevee

+0

http://stackoverflow.com/a/19257335/419348 왜'super (self .__ class__, self) .baz (arg) '를 호출하지 말아야하는지에 대해서 말했습니다. – AechoLiu

9

내가 여기에이

class A: 
    def __init__(self): 
     print "I am Class %s"%self.__class__.__name__ 
     for parentClass in self.__class__.__bases__: 
       print " I am inherited from:",parentClass.__name__ 
       #parentClass.foo(self) <- call parents function with self as first param 
class B(A):pass 
class C(B):pass 
a,b,c = A(),B(),C() 
+0

나는 말할 말을 찾고있었습니다. 여기에서 찾을 수 있습니다. 감사합니다! – zVictor

+0

여기에서 ** super **에 대한 참조의 볼륨에서 알 수 있듯이, 여러분은 정말로 깊은 것을하지 않는 한 __bases__를 사용하는 것이 정말 싫어합니다. 당신은 ** super **, ** mro **를 보지 마라. ** mro **에서 첫 번째 엔트리를 얻는 것은 __bases__에서 어떤 엔트리를 추적하는 것보다 안전하다 .Python의 다중 상속은 어떤 것을 뒤에서 그리고 다른 것들을 스캔한다. 앞으로, 언어를 풀어 놓는 것이 가장 안전합니다. –

24

같은 CLASS.__bases__ 뭔가를 사용하는 것이 좋습니다는 슈퍼()을 사용하는 예제입니다

#New-style classes inherit from object, or from another new-style class 
class Dog(object): 

    name = '' 
    moves = [] 

    def __init__(self, name): 
     self.name = name 

    def moves_setup(self): 
     self.moves.append('walk') 
     self.moves.append('run') 

    def get_moves(self): 
     return self.moves 

class Superdog(Dog): 

    #Let's try to append new fly ability to our Superdog 
    def moves_setup(self): 
     #Set default moves by calling method of parent class 
     super(Superdog, self).moves_setup() 
     self.moves.append('fly') 

dog = Superdog('Freddy') 
print dog.name # Freddy 
dog.moves_setup() 
print dog.get_moves() # ['walk', 'run', 'fly']. 
#As you can see our Superdog has all moves defined in the base Dog class 
+0

나쁜 예가 아닌가요? 나는 당신의 전체 계층 구조가 "새로운 스타일"클래스이고 적절하게 Super()를 호출하지 않는 한 Super를 사용하는 것이 안전하지 않다고 믿는다. init() – Jaykul

4

파이썬에는 super()도 있습니다. 하나는 상술하는 수퍼 클래스 방법은 서브 클래스의 메소드

class Dog(object): 
    name = '' 
    moves = [] 

    def __init__(self, name): 
     self.name = name 

    def moves_setup(self,x): 
     self.moves.append('walk') 
     self.moves.append('run') 
     self.moves.append(x) 
    def get_moves(self): 
     return self.moves 

class Superdog(Dog): 

    #Let's try to append new fly ability to our Superdog 
    def moves_setup(self): 
     #Set default moves by calling method of parent class 
     super().moves_setup("hello world") 
     self.moves.append('fly') 
dog = Superdog('Freddy') 
print (dog.name) 
dog.moves_setup() 
print (dog.get_moves()) 

이 예에서 호출 방법에 대한

예와 유사하다.그러나 super에는 전달 된 인수가 하나도 없다는 단점이 있습니다. 위의 코드는 Python 3.4 버전에서 실행 가능합니다.

19

파이썬 3가있다 부모 메소드를 호출하기위한 다른 간단하고 간단한 구문. super().__init__()를 사용하여 다음 Bar.__init__에서 Foo에서 호출 할 수 있습니다 Bar에서 Foo 경우에 클래스 상속 :

class Foo(Bar): 
    def __init__(self): 
     super().__init__() 
+1

파이썬 3은 더 좋은 해결책이있다. 질문은 파이썬 2.X에서옵니다. 생각해 줘서 고마워. ''' 대신 ''''클래스 A()의':'''' 그런 다음 슈퍼() 아니에요 – jjohn

1

파이썬 2에서, 나는 슈퍼과 많은 행운이 없었다(). 이 how to refer to a parent method in python?에 jimifiki의 답변을 사용했습니다. 그런 다음, 필자는 약간의 비틀기를 추가했다. 특히 유용성이 향상되었다고 생각한다. (특히 클래스 이름이 긴 경우).

것은 하나 개의 모듈에 기본 클래스를 정의

# myB.py 

from myA import A as parent 

class B(parent): 
    def foo(self): 
     parent.foo(self) # calls 'A.foo()' 
+1

당신은 은''''클래스 A (객체)를 사용해야합니다 나는 따라와. 수업의 정의를 의미합니까? 분명히, 당신은 부모님이 어떻게해서든지 당신이 부모를 참조 할 수 있다고 생각하기 위해서 부모를 가지고 있다는 것을 나타내야합니다! 9 개월 전이 글을 게시 한 이래로, 세부 사항은 약간 희미하지만 Arun Ghosh, lawrence, kkk 등의 예제는 Py 2.x에는 적용되지 않는다고 생각합니다. 대신, 여기에 작동하는 방법과 부모를 참조하는 쉬운 방법 그래서 당신이 뭘하는지 조금 더 분명해. (super 사용) – blndev

+0

작동합니다 – BuvinJ

8

많은 답변이되었습니다 부모의 메소드 호출하는 방법을 설명했다 :

# myA.py 

class A():  
    def foo(self): 
     print "foo" 

그런 다음 다른 모듈 as parent으로 클래스를 가져 아이가 무시됩니다.

그러나

"how do you call a parent class's method from child class?"

또한 단지 의미 할 수있다 :

"how do you call inherited methods?"

당신은, 그들이 자식 클래스의 방법 인 것처럼 부모 클래스에서 상속되는 메서드를 호출 할 수 있습니다만큼 그들은 천국으로 ' 덮어 썼습니다.

파이썬 3 :

class A(): 
    def bar(self, string): 
    print("Hi, I'm bar, inherited from A"+string) 

class B(A): 
    def baz(self): 
    self.bar(" - called by baz in B") 

B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B" 

네, 이것은 매우 분명있을 수 있습니다,하지만 난이 문제를 지적하지 않고 사람들이 그냥 파이썬에서 액세스 상속 방법에 말도 농구를 통해 이동해야하는 인상이 스레드를 떠날 수 있다고 생각합니다. 특히이 질문은 "부모 클래스의 메소드를 Python으로 액세스하는 방법"에 대한 검색에서 매우 중요하며, OP는 Python을 처음 사용하는 사람의 관점에서 작성되었습니다.

발견 : https://docs.python.org/3/tutorial/classes.html#inheritance 상속 된 메서드에 액세스하는 방법을 이해하는 데 유용합니다.

+0

정확히 알고 싶습니다. 감사 :) – Chad

관련 문제