자식 클래스에서 부모 클래스의 메서드를 호출합니까?


606

파이썬에서 간단한 객체 계층을 만들 때 파생 클래스에서 부모 클래스의 메서드를 호출 할 수 있기를 원합니다. Perl과 Java에는이 키워드 ( super)에 대한 키워드가 있습니다. Perl에서는 다음과 같이 할 수 있습니다.

package Foo;

sub frotz {
    return "Bamf";
}

package Bar;
@ISA = qw(Foo);

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

파이썬에서는 자식 클래스에서 부모 클래스의 이름을 명시 적으로 지정해야합니다. 위의 예에서와 같은 작업을 수행해야합니다 Foo::frotz().

이 동작으로 인해 깊은 계층 구조를 만드는 것이 어려워지기 때문에 이것은 옳지 않은 것 같습니다. 자녀가 상속받은 메소드를 정의한 클래스를 알아야하는 경우 모든 종류의 정보 고통이 발생합니다.

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


3
부모 클래스의 이름은 그렇게 나쁜 생각이 아니라고 생각합니다. 부모 클래스의 이름을 명시 적으로 지정하므로 자식 클래스가 둘 이상의 부모로부터 상속 될 때 도움이 될 수 있습니다.

7
클래스 이름을 짓는 옵션은 나쁜 생각은 아니지만 확실히 그렇게하는 것이 좋습니다.
johndodo

Python 2와 Python 3 https://www.python.org/dev/peps/pep-3135/ 간의 수퍼 핸들링 변경 사항에 유의 하십시오 . 클래스 이름을 더 이상 지정할 필요가 없습니다 (적어도 때로는 신의 아이디어 일 수도 있지만).
jwpfox

답변:


735

네,하지만 새로운 스타일의 클래스 에서만 가능 합니다. super()기능을 사용하십시오 :

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

python <3의 경우 다음을 사용하십시오.

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

53
"return Bar.baz (self, arg)"도 할 수 없습니까? 그렇다면 어느 것이 더 좋을까요?

15
그렇습니다.하지만 OP는 호출 사이트 (이 경우 Bar)에서 수퍼 클래스를 명시 적으로 지정하지 않고 수행 방법을 묻고있었습니다.
Adam Rosenfield

7
super ()는 다중 상속에서 이상합니다. "다음"클래스를 호출합니다. 부모 클래스이거나 계층의 다른 곳에 나타나는 완전히 관련이없는 클래스 일 수 있습니다.
Steve Jessop

6
저는 Python 2.x를 사용하는데, 이렇게하면 "오류 : classobj가 아니라 형식이어야합니다"라는 메시지가 나타납니다.
Chris F

28
구문 super(Foo, self)은 Python 2.x에 대한 것입니까? Python 3.x에서 super()선호되는 것이 맞습니까?
Trevor Boyd Smith

143

파이썬에는 슈퍼 도 있습니다.

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

메서드 호출을 부모 또는 형제 유형의 클래스에 위임하는 프록시 객체를 반환합니다. 클래스에서 재정의 된 상속 된 메서드에 액세스하는 데 유용합니다. 검색 순서는 유형 자체를 건너 뛰는 것을 제외하고 getattr ()에서 사용 된 것과 동일합니다.

예:

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

7
객체 기반 클래스와 함께 새로운 스타일의 클래스를 사용하는 것을 시연했기 때문에 Adam보다 더 나은 예입니다. 새로운 스타일의 클래스에 대한 링크가 없습니다.
사무엘

82
ImmediateParentClass.frotz(self)

직계 부모 클래스가 frotz자체적으로 정의했는지 아니면 상속 했는지에 관계없이 괜찮 습니다. 다중 상속 super을 올바르게 지원하는 데만 필요합니다 (그리고 모든 클래스가 올바르게 사용하는 경우에만 작동합니다). 일반적으로 정의하지 않거나 재정의하지 않으면 조상 을 찾아 볼 것 입니다. 이는 "자식을 호출하는 부모 클래스의 메소드"에 대해서도 발생합니다.AnyClass.whateverwhateverAnyClassAnyClass


이 명령을 실행하려면 ImmediateParentClass도 범위 내에 있어야합니다. 모듈에서 오브젝트를 가져 오는 것만으로는 도움이되지 않습니다.
Tushar Vazirani

클래스 메소드라면?
Shiplu Mokaddim

@TusharVazirani 부모 클래스가 즉각적 parent이라면 전체 클래스의 범위에 있지 않습니까?
Yaroslav Nikitenko

1
@YaroslavNikitenko 클래스가 아닌 인스턴스 가져 오기에 대해 이야기하고 있습니다.
Tushar Vazirani

1
@TusharVazirani 이제 이해합니다, 감사합니다. 현재 클래스의 메소드에서 호출하는 것에 대해 생각하고있었습니다 (OP에 명시된 바와 같이).
Yaroslav Nikitenko

74

파이썬 3 은 부모 메소드를 호출하기위한 다른 간단하고 간단한 구문을 가지고 있습니다.

Foo클래스가에서 상속받은 경우 Bar다음 Bar.__init__Foo통해 from 을 호출 할 수 있습니다 super().__init__().

class Foo(Bar):

    def __init__(self, *args, **kwargs):
        # invoke Bar.__init__
        super().__init__(*args, **kwargs)

5
파이썬 3에는 더 나은 해결책이 있습니다. 문제는 python 2.X에서 나옵니다. 그래도 제안 해 주셔서 감사합니다.
jjohn

45

많은 답변이 자식에서 재정의 된 부모로부터 메서드를 호출하는 방법을 설명했습니다.

하나

"자식 클래스에서 부모 클래스의 메소드를 어떻게 호출합니까?"

또한 의미 할 수 있습니다 :

"상속 된 메소드를 어떻게 호출합니까?"

덮어 쓰지 않는 한 자식 클래스의 메서드 인 것처럼 부모 클래스에서 상속 된 메서드를 호출 할 수 있습니다.

예를 들어 파이썬 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"

그렇습니다. 이것은 상당히 분명 할 수 있지만 사람들이 지적하지 않으면 사람들이 파이썬에서 상속 된 메소드에 액세스하기 위해 어리석은 농구 대를 뛰어 넘어야한다는 인상을 남길 수 있다고 생각합니다. 특히이 질문은 "파이썬에서 부모 클래스의 메소드에 액세스하는 방법"에 대한 검색에서 높은 평가를 받고 OP는 파이썬을 처음 접하는 사람의 관점에서 작성됩니다.

상속 된 메소드에 액세스하는 방법을 이해하는 데 유용한 https://docs.python.org/3/tutorial/classes.html#inheritance 를 찾았습니다 .


어떤 상황에서 @ gizzmole이 작동하지 않습니까? 관련된 경고 나 경고를 추가하게되어 기쁘지만 게시 한 링크가이 답변과 어떤 관련이 있는지 알 수 없었습니다.
Ben

@Ben 죄송합니다. 답을 충분히 읽지 못했습니다. 이 답변은 함수를 오버로드하는 방법에 대한 질문에는 대답하지 않지만 다른 질문에 대답합니다. 초기 의견을 삭제했습니다.
gizzmole

@ gizzmole 아, 걱정하지 마십시오. 이 답변은 과부하 기능에는 적용되지 않지만 문제는 명시 적으로 과부하를 언급하지 않습니다 (주어진 perl 예제는 과부하의 경우를 보여 주지만). 다른 답변의 대부분은 과부하를 다루고 있습니다. 이것은 필요없는 사람들을 위해 여기 있습니다.
Ben

@B에 정의 된 변수를 사용하여 'C'라는 다른 클래스에서 B (). baz ()를 호출하려면 어떻게해야합니까? self.string이 또 다른 val 인 클래스 C에서 B (). baz ()를 시도했습니다. 내가 처형했을 때 그것은 나에게 아무것도주지 않았다
joey

@joey 나는 당신이 무엇을하려고하는지, 그것이이 질문의 범위 내에 있는지 확실하지 않습니다. 문자열은 로컬 변수 self.string입니다. 설정 은 아무 것도하지 않습니다. C 클래스에서는 여전히 전화 할 수 있습니다B().bar(string)
Ben

26

다음은 super () 사용 예입니다 .

#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

이것은 나쁜 예가 아닙니까? 전체 계층 구조가 "새 스타일"클래스이고 Super (). init ()를 올바르게 호출하지 않으면 Super를 사용하는 것이 실제로 안전하지 않다고 생각합니다.
Jaykul

13

파이썬에는 super ()도 있습니다. 파이썬의 구식과 새로운 스타일의 클래스 때문에 약간 까다 롭지 만 생성자에서 매우 일반적으로 사용됩니다.

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

9

나는 CLASS.__bases__ 이런 것을 사용하는 것이 좋습니다

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

1
여기서 수퍼 에 대한 언급에서 알 수 있듯이 사람들은 정말로 깊은 일을하지 않는 한 기지 를 사용하는 것을 정말로 싫어합니다 . super가 마음에 들지 않으면 mro보십시오 . mro 에서 첫 번째 항목 을 사용하는 것이 사용할 기본 항목을 추적하는 것보다 안전 합니다. 파이썬의 다중 상속은 특정 것들을 뒤로 스캔하고 다른 것들을 앞으로 스캔하므로 언어가 프로세스를 풀어주는 것이 가장 안전합니다.
존 제이 오버 마크


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 버전에서 실행 가능합니다.


2

이 예 cafec_param에서 기본 클래스 (부모 클래스) abc는 하위 클래스입니다. 기본 클래스에서 메소드를 abc호출합니다 AWC.

class cafec_param:

    def __init__(self,precip,pe,awc,nmonths):

        self.precip = precip
        self.pe = pe
        self.awc = awc
        self.nmonths = nmonths

    def AWC(self):

        if self.awc<254:
            Ss = self.awc
            Su = 0
            self.Ss=Ss
        else:
            Ss = 254; Su = self.awc-254
            self.Ss=Ss + Su   
        AWC = Ss + Su
        return self.Ss


    def test(self):
        return self.Ss
        #return self.Ss*4

class abc(cafec_param):
    def rr(self):
        return self.AWC()


ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())

산출

56

56

56

1

파이썬 2에서는 super ()로 운이 없었습니다. 나는이 SO 스레드에서 jimifiki의 대답을 파이썬에서 부모 메소드를 참조하는 방법을 사용 했습니까? . 그런 다음 사용 방법이 향상되었다고 생각합니다 (특히 클래스 이름이 긴 경우).

하나의 모듈에서 기본 클래스를 정의하십시오.

 # myA.py

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

그런 다음 클래스를 다른 모듈로 가져옵니다 as parent.

# myB.py

from myA import A as parent

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

2
당신은 사용할 필요가 class A(object): 대신 class A(): 작동합니다 그리고 슈퍼 ()
blndev

잘 모르겠습니다. 클래스의 정의를 의미합니까? 분명히, 당신은 부모님을 언급 할 수 있다고 생각하기 위해 어떻게 든 클래스에 부모가 있다는 것을 나타내야합니다! 이 9 개월 전에 게시 한 이후 세부 사항에 대해 조금 모호하지만 Arun Ghosh, lawrence, kkk 등의 예제는 Py 2.x에 해당되지 않는다고 생각합니다. 대신, 여기에 작동하는 방법과 부모를 쉽게 참조 할 수있는 방법이 있으므로 수행중인 작업이 조금 더 명확합니다. (super를 사용하는 것과 같은)
BuvinJ

-1
class department:
    campus_name="attock"
    def printer(self):
        print(self.campus_name)

class CS_dept(department):
    def overr_CS(self):
        department.printer(self)
        print("i am child class1")

c=CS_dept()
c.overr_CS()

-4
class a(object):
    def my_hello(self):
        print "hello ravi"

class b(a):
    def my_hello(self):
    super(b,self).my_hello()
    print "hi"

obj = b()
obj.my_hello()

2
stackoverflow에 오신 것을 환영합니다. 이 질문은 거의 10 년 전에 이미 상세하게 답변되었으며, 그 대답은 받아 들여지고 크게 상향 조정되었으며, 귀하의 답변은 새로운 것을 추가하지 않습니다. 당신은 대신에 더 최근의 (그리고 바람직하게는 대답하지 않은) 질문을 시도하고 대답 할 수 있습니다. 참고로, 편집기에는 올바른 코드 형식을 적용 할 수있는 버튼이 있습니다.
bruno desthuilliers

-24

이것은 더 추상적 인 방법입니다.

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

15
self는 항상 인스턴스이고 클래스 는 항상 인스턴스 클래스 이므로 self .__ class__는 super와 올바르게 작동하지 않습니다 . 즉, 클래스에서 super (self .__ class__ ..를 사용하고 해당 클래스가 상속되면 더 이상 작동하지 않습니다.
xitrium

16
강조하기 위해이 코드를 사용하지 마십시오. MRO를 올바르게 통과하는 super ()의 전체 목적을 무효화합니다.
Eevee

1
stackoverflow.com/a/19257335/419348가 전화를 걸지 않은 이유를 말했습니다 super(self.__class__, self).baz(arg).
AechoLiu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.