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

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

인터넷 검색을 통해 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)



답변

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

답변

단일 상속의 경우 (한 클래스 만 하위 클래스로 지정하는 경우) 새 클래스는 기본 클래스의 메서드를 상속합니다. 여기에는 __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는 해당 메서드가 한 번만 호출되도록 보장한다는 것입니다.


답변

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

(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/를 참조 할 수 있습니다 .


답변

대부분의 사람들이 지금 사용하고있는 것처럼 보이는 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


답변

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


답변