code

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

codestyles 2020. 9. 13. 10:33
반응형

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

Notice how both base classes use super even though they don't have their own base classes.

What super does is: it calls the method from the next class in MRO (method resolution order). The MRO for C is: (C, A, B, object). You can print C.__mro__ to see it.

So, C inherits __init__ from A and super in A.__init__ calls B.__init__ (B follows A in MRO).

So by doing nothing in C, you end up calling both, which is what you want.

Now if you were not using super, you would end up inheriting A.__init__ (as before) but this time there's nothing that would call B.__init__ for you.

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

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

class C(A, B):
    pass

C()
#prints:
#A

To fix that you have to define C.__init__:

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

The problem with that is that in more complicated MI trees, __init__ methods of some classes may end up being called more than once whereas super/MRO guarantee that they're called just once.


In short, they are equivalent. Let's have a history view:

(1) at first, the function looks like this.

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

(2) to make code more abstract (and more portable). A common method to get Super-Class is invented like:

    super(<class>, <instance>)

And init function can be:

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

However requiring an explicit passing of both the class and instance break the DRY (Don't Repeat Yourself) rule a bit.

(3) in V3. It is more smart,

    super()

is enough in most case. You can refer to http://www.python.org/dev/peps/pep-3135/


Just to have a simple and complete example for Python 3, which most people seem to be using now.

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)

gives

42
chickenman

Another python3 implementation that involves the use of Abstract classes with super(). You should remember that

super().init(name, 10)

has the same effect as

Person.init(self, name, 10)

Remember there's a hidden 'self' in super(), So the same object passes on to the superclass init method and the attributes are added to the object that called it. Hence super()gets translated to Person and then if you include the hidden self, you get the above code frag.

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

참고URL : https://stackoverflow.com/questions/10482953/python-extending-with-using-super-python-3-vs-python-2

반응형