Python 확장-super () Python 3 대 Python 2 사용


103

원래는 이 질문을 하고 싶었지만 , 이미 생각했던 것 같았습니다 ...

인터넷 검색을 통해 configparser 확장 예제를 찾았습니다 . 다음은 Python 3에서 작동합니다.

$ python3
Python 3.2.3rc2 (default, Mar 21 2012, 06:59:51) 
[GCC 4.6.3] on linux2
>>> from configparser import  SafeConfigParser
>>> class AmritaConfigParser(SafeConfigParser):
...     def __init_(self):
...         super().__init__()
... 
>>> cfg = AmritaConfigParser()

그러나 Python 2에서는 그렇지 않습니다.

>>> class AmritaConfigParser(SafeConfigParser):
...       def __init__(self):
...           super(SafeConfigParser).init()
... 
>>> cfg = AmritaConfigParser()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __init__
TypeError: must be type, not classob

그런 다음 Python New Class vs. Old Class 스타일에 대해 조금 읽었습니다 (예 : 여기 . 이제 궁금합니다.

class MyConfigParser(ConfigParser.ConfigParser):
      def Write(self, fp):
          """override the module's original write funcition"""
          ....
      def MyWrite(self, fp):
          """Define new function and inherit all others"""

하지만 init를 호출하면 안되나요? 이것은 Python 2에서 동등합니까?

 class AmritaConfigParser(ConfigParser.SafeConfigParser):
    #def __init__(self):
    #    super().__init__() # Python3 syntax, or rather, new style class syntax ...
    #
    # is this the equivalent of the above ? 
    def __init__(self):
        ConfigParser.SafeConfigParser.__init__(self)

1
귀하의 예제 __init__()에서 수퍼 클래스를 호출하는 것이 전부라면 서브 클래스에서을 정의 할 필요가 없습니다 __init__()(파이썬 2 또는 3에서)-대신 수퍼 클래스 가 상속되도록하십시오.
martineau 2013 년


수정 링크 유용한 참조 : amyboyle.ninja/Python-Inheritance이
fearless_fool

답변:


155
  • super()(인수없이) Python 3에서 도입되었습니다 (와 함께 __class__) :

    super() -> same as super(__class__, self)

    새 스타일 클래스에 해당하는 Python 2입니다.

    super(CurrentClass, self)
  • 구식 클래스의 경우 항상 다음을 사용할 수 있습니다.

     class Classname(OldStyleParent):
        def __init__(self, *args, **kwargs):
            OldStyleParent.__init__(self, *args, **kwargs)

8
-1. 이 대답은 나를 위해 아무것도 명확하지 않았습니다. Python 2에서는,를 super(__class__)제공 NameError: global name '__class__' is not defined하고 super(self.__class__)오류도 발생합니다. 당신은 있어야 당신이 할 필요가 제안 두 번째 인수로 인스턴스를 제공 super(self.__class__, self)하지만, 즉 잘못된 . 경우 Class2에서 상속 Class1Class1전화 super(self.__class__, self).__init__(), Class1의는 __init__다음 것 자체를 호출 의 인스턴스를 인스턴스화 할 때 Class2.
jpmc26

요점을 명확히하기 위해 Python 2 TypeError: super() takes at least 1 argument (0 given)를 호출하려고 할 때 얻습니다 super(self.__class__). (별로 이해가되지는 않지만이 답변에서 얼마나 많은 정보가 누락되었는지 보여줍니다.)
jpmc26

3
@ jpmc26 : python2 __init__()에서는 바인딩되지 않은 슈퍼 개체 ( super(self.__class__)하나의 인수 만 사용 하여 호출)에 인수없이 호출하려고 하면 바인딩 된 슈퍼 개체 가 필요하기 때문에이 오류가 발생합니다 super(CurrentClass, self).__init__(). 부모를 호출 할 때 self.__class__항상 동일한 클래스를 참조하고 그 부모도 동일한 작업을 수행하면 무한 루프를 생성 하므로 사용하지 마십시오 .
mata jul.

__class__(멤버)는 Python2 에도 있습니다 .
CristiFati

3
@CristiFati 이것은 __class__멤버에 관한 것이 아니라 python2에 존재하지 않는 현재 정의되고있는 클래스를 항상 참조 하는 암시 적으로 생성 된 어휘 __class__클로저에 관한 것입니다.
mata

48

단일 상속의 경우 (한 클래스 만 하위 클래스로 지정하는 경우) 새 클래스는 기본 클래스의 메서드를 상속합니다. 여기에는 __init__. 따라서 클래스에서 정의하지 않으면 기본에서 가져옵니다.

다중 상속을 도입하면 상황이 복잡해지기 시작합니다 (한 번에 둘 이상의 클래스를 서브 클래 싱). 이는 둘 이상의 기본 클래스에가있는 __init__경우 클래스가 첫 번째 클래스 만 상속하기 때문입니다.

그런 경우에는 할 수 있으면 정말 써야 super하는데 그 이유를 설명하겠습니다. 하지만 항상 그런 것은 아닙니다. 문제는 모든 기본 클래스가이를 사용해야한다는 것입니다 (그리고 기본 클래스도 전체 트리).

이 경우에도 올바르게 작동합니다 (Python 3에서하지만 Python 2로 재 작업 할 수 있습니다. 또한 super) :

class A:
    def __init__(self):
        print('A')
        super().__init__()

class B:
    def __init__(self):
        print('B')
        super().__init__()

class C(A, B):
    pass

C()
#prints:
#A
#B

super자체 기본 클래스가 없더라도 두 기본 클래스가 어떻게 사용되는지 확인하십시오 .

어떤 super일은이다 : 그것은 MRO의 다음 클래스의 방법 (방법 확인 순서)를 호출합니다. 의 MRO C: (C, A, B, object). 인쇄 C.__mro__하여 볼 수 있습니다 .

따라서, C상속 __init__에서 AsuperA.__init__통화 B.__init__( B다음 AMRO에).

따라서에서 아무것도하지 C않으면 결국 둘 다 호출하게됩니다.

이제를 사용하지 않으면 이전과 마찬가지로 super상속하게 A.__init__되지만 이번에는 호출 B.__init__할 항목이 없습니다.

class A:
    def __init__(self):
        print('A')

class B:
    def __init__(self):
        print('B')

class C(A, B):
    pass

C()
#prints:
#A

이를 수정하려면 다음을 정의해야합니다 C.__init__.

class C(A, B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)

문제는 더 복잡한 MI 트리에서는 __init__일부 클래스의 메서드가 두 번 이상 호출 될 수있는 반면 super / MRO는 해당 메서드가 한 번만 호출되도록 보장한다는 것입니다.


10
Notice how both base classes use super even though they don't have their own base classes.그들은 가지고 있습니다. py3k에서 모든 클래스 하위 클래스 개체.
akaRem

이것이 제가 찾던 대답이지만 어떻게 묻는 지 몰랐습니다. MRO 설명이 좋습니다.
dturvene

27

간단히 말해 동등합니다. 히스토리 뷰를 보겠습니다.

(1) 처음에는 함수가 이렇게 생겼습니다.

    class MySubClass(MySuperClass):
        def __init__(self):
            MySuperClass.__init__(self)

(2) 코드를보다 추상적이고 이식 가능하게 만들기 위해. Super-Class를 얻는 일반적인 방법은 다음과 같이 발명되었습니다.

    super(<class>, <instance>)

초기화 함수는 다음과 같습니다.

    class MySubClassBetter(MySuperClass):
        def __init__(self):
            super(MySubClassBetter, self).__init__()

그러나 클래스와 인스턴스의 명시 적 전달을 요구하면 DRY (Do n't Repeat Yourself) 규칙이 약간 어긋납니다.

(3) V3에서. 더 똑똑하고

    super()

대부분의 경우 충분합니다. http://www.python.org/dev/peps/pep-3135/를 참조 할 수 있습니다 .


22

대부분의 사람들이 지금 사용하고있는 것처럼 보이는 Python 3에 대한 간단하고 완전한 예제를 가지려고합니다.

class MySuper(object):
    def __init__(self,a):
        self.a = a

class MySub(MySuper):
    def __init__(self,a,b):
        self.b = b
        super().__init__(a)

my_sub = MySub(42,'chickenman')
print(my_sub.a)
print(my_sub.b)

준다

42
chickenman

3

super ()와 함께 Abstract 클래스를 사용하는 또 다른 python3 구현입니다. 당신은 그것을 기억해야합니다

super().__init__(name, 10)

다음과 같은 효과가 있습니다.

Person.__init__(self, name, 10)

super ()에는 숨겨진 'self'가 있으므로 동일한 객체가 수퍼 클래스 init 메서드로 전달되고 속성이이를 호출 한 객체에 추가됩니다. 따라서 super()로 번역되고 Person숨겨진 자아를 포함하면 위의 코드 조각이 나타납니다.

from abc import ABCMeta, abstractmethod
class Person(metaclass=ABCMeta):
    name = ""
    age = 0

    def __init__(self, personName, personAge):
        self.name = personName
        self.age = personAge

    @abstractmethod
    def showName(self):
        pass

    @abstractmethod
    def showAge(self):
        pass


class Man(Person):

    def __init__(self, name, height):
        self.height = height
        # Person.__init__(self, name, 10)
        super().__init__(name, 10)  # same as Person.__init__(self, name, 10)
        # basically used to call the superclass init . This is used incase you want to call subclass init
        # and then also call superclass's init.
        # Since there's a hidden self in the super's parameters, when it's is called,
        # the superclasses attributes are a part of the same object that was sent out in the super() method

    def showIdentity(self):
        return self.name, self.age, self.height

    def showName(self):
        pass

    def showAge(self):
        pass


a = Man("piyush", "179")
print(a.showIdentity())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.