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/
'python' 카테고리의 다른 글
파이썬 데코레이터 활용(로깅) (1) | 2021.09.02 |
---|---|
python oracle 데이터 json serialize(django) (0) | 2020.02.25 |
python 메모리 관리(memory allocation) (4) | 2019.11.15 |
클래스 관계 IS-A 상속 (0) | 2019.11.07 |
python openpyxl을 이용한 Django DB insert (0) | 2019.06.21 |