python에서 super란 정확히 무엇인가?? Django 프레임워크와 같이 상속을 이리저리 받고 MIXIN 쓰고 하면 헷갈린다.

 

 

super

super() alone returns a temporary object of the superclass that then allows you to call that superclass’s methods.

 

슈퍼(부모) 클래스의 임시 object를 리턴한다. 이 임시 object로 슈퍼 클래스의 메소드를 사용할 수 있다.!

그러니 super()라고 쓰면 부모 클래스의 object를 가져와서 부모 클래스의 say_hi() 같은 메소드를 사용할 수 있다는 말이다.

 

 

간단한 Super 예제(상속 전)
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width

class Square:
    def __init__(self, length):
        self.length = length

    def area(self):
        return self.length * self.length

    def perimeter(self):
        return 4 * self.length

square = Square(4)
print(square.area())

rectangle = Rectangle(2,4)
print(rectangle.area())

Square(정사각형)은 Rectangle(직사각형)의 특별한 케이스다. 그러므로 상속으로 코드를 줄일 수 있다.

 

간단한 Super 예제(상속 후)
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width

class Square(Rectangle):
    def __init__(self, length):
        super().__init__(length, length)
        
        
square = Square(4)
print(square.area())

rectangle = Rectangle(2,4)
print(rectangle.area())
        

이런식으로 Rectangle을 상속 받아서 사용하면 부모 클래스인 Rectangle의 are() 메소드를 사용할 수 있다.

Square의 __init__에서 super().__init__(length, length)라고 코딩했는데 이 호출에 따라서 Rectangle의 Class 오브젝트를 생성한다. 이렇게 Rectangle 오브젝트를 생성해야 area 메소드를 사용할 수 있다. 왜냐하면 area 메소드는 self.length와 self.width를 가지기 때문이다. (__init__을 호출해야 self.length, self.width 값이 정확히 생성됨)

 

 

super() vs super(클래스 이름, self)

위의  예제에서는 super()라고 포현했는데 다른 코드를 보면 super(Squre, self).__init__() 이런 식으로 표현하는 곳도 볼 수있다.

super()와 super(Squre, self) 은 무엇이 다를까?

사실 super는 두개의 파라미터를 받는데 처음은 하위클래스의 이름, 두번째는 하위클래스의 object다. 위의 예제에서는

super()와 super(Squre, self) 두개로 표현될 수 있는데 위의 예제의 경우에는 어떻게 표현하든 똑같다.

하지만 다중 상속 및 할머니 상속일 경우 의미가 살짝 다른데 첫번째 매개변수의 클래스 이름에 따라 super 가 탐색하는 범위가 달라진다.

 

 

부모의 부모(할머니)로 부터 상속
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        print('할머니 area')
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width


class Square(Rectangle):
    def __init__(self, length):
        self.length = length
        super().__init__(length, length)

    def area(self):
        print('부모의 area')
        return self.length * self.length


class Cube(Square):
    def surface_area(self):
        face_area = super(Square, self).area()
        return face_area * 6

    def volume(self):
        face_area = super().area()
        return face_area * self.length


cube = Cube(3)
print(cube.surface_area())
# 할머니 area
# 54
print(cube.volume())
# 부모의 area
# 27

Cube Class의 surface_area와 volume 메소드는 모두 부모의 area 메소드가 필요하다.

이때 하나는 super(Square, self)를 하나는 super()를 사용했다. 

 

super(Square, self)를 사용한 surface_area는 할머니 즉 Rectangle에서 가져왔고 그냥 super()를 사용한 volume은 부모의 area를 사용했다.

 

아까 말했다 싶이 탐색범위가 달라진다고 했다 그러니깐 Square를 명시한 super는 Square의 부모로 부터 탐색한다. 그래서 Rectangle(할머니)의 area를 호출했다.

 

참고 사이트 : https://realpython.com/python-super/

+ Recent posts