[Python] self, __init__, 추상 클래스, 상속, 클래스 변수, 객체 변수
self
파이썬 메서드의 첫 번째 인자로 항상 인스턴스가 전달된다.
class Foo:
def func1():
print("function 1")
def func2(self):
print("function 2")
>>> f = Foo()
>>> f.func2()
function 2
>>>
이때 func2()를 호출하면 잘 작동한다. 호출할 때는 아무것도 전달하지 않는 이유는 첫 번째 인자인 self에 대한 값은 파이썬이 자동으로 넘겨주기 때문이다.
>>> f.func1()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
f.func1()
TypeError: func1() takes 0 positional arguments but 1 was given
>>>
하지만, 인스턴스를 통해 func1()을 호출해보면 오류가 발생한다.
오류 메시지를 살펴보면 “func1()은 인자가 없지만 하나를 받았다”라는 것을 볼 수 있다.
이는 파이썬 메서드의 첫 번째 인자로 항상 인스턴스가 전달되기 때문에 발생하는 문제이다.
그렇다면 self의 정체는 무엇일까?
self는 클래스 내에 정의된 self는 클래스 인스턴스이다.
>>> class Foo:
def func1():
print("function 1")
def func2(self):
print(id(self))
print("function 2")
>>>
# 인스턴스 f가 메모리에 할당된 주솟값 출력
>>> f = Foo()
>>> id(f)
43219856
>>>
# 인스턴스 f가 func2 메소드 호출
# self가 메모리에 할당된 주솟값 출력 - print(id(self))
>>> f.func2()
43219856
function 2
>>>
위와 같은 코드를 실행했을 때 인스턴스 f가 메모리에 할당된 주솟값과 self가 메모리에 할당된 주솟값은 같다.
즉, 클래스 내에 정의된 self는 클래스 인스턴스임을 알 수 있다.
__init__
- 컨스트럭터라고 불리는 초기화를 위한 함수(메소드) - 자바의 생성자 같은 것
- 인스턴스화를 실시할 때 반드시 처음에 호출되는 특수한 함수
- 오브젝트 생성(인스턴스를 생성)과 관련하여 데이터의 초기를 실시하는 함수
class MyStatus:
def __init__(self,age,name,height,weight):
self.age = age
self.name = name
self.height = height
self.weight = weight
def print_name(self):
print(self.name)
def print_age(self):
print(self.age)
def print_height(self):
print(self.height)
def print_weight(self):
print(self.weight)
a = MyStatus(34,"yamada",170,78)
상속
class 부모클래스:
...내용...
class 자식클래스(부모클래스):
...내용...
- 자식클래스를 선언할때 소괄호로 부모클래스를 포함시킨다.
- 자바와 달리 다중상속이 가능하다.
class Country:
"""Super Class"""
name = '국가명'
population = '인구'
capital = '수도'
def show(self):
print('국가 클래스의 메소드입니다.')
class Korea(Country):
"""Sub Class"""
def __init__(self, name):
self.name = name
def show_name(self):
print('국가 이름은 : ', self.name)
추상 클래스
파이썬에서는 추상클래스를 통해 이를 상속하는 클래스들에게 특정 메소드의 구현을 강제할 수 있다.
자바의 경우에는 interface가 같은 역할을 한다.
추상 클래스를 만들려면 import로 abc 모듈을 가져와야 한다.
abc는 abstract base class의 약자이다.
from abc import *
class 추상클래스이름(metaclass=ABCMeta):
@abstractmethod
def 메서드이름(self):
코드
일단 추상 클래스를 만든 모습이다.
추상클래스 옆에 (metaclass=ABCMeta)를 써준다.
그럼 추상클래스 StudentBase를 만들고, 이를 상속받아서 구현한 Student 클래스를 만들어보자.
from abc import *
class StudentBase(metaclass=ABCMeta): # 추상클래스
@abstractmethod # 추상메소드
def study(self):
pass
@abstractmethod
def go_to_school(self):
pass
class Student(StudentBase): # StudentBase를 상속받아서 구현한 구현클래스
def study(self): # 추상메소드를 구현
print('공부하기')
def go_to_school(self):
print('학교가기')
james = Student() # Student 클래스 인스턴스 생성
james.study()
james.go_to_school()
Student 클래스의 인스턴스를 생성하고 study, go_to_school과 같은 메소드를 호출하면 재정의(overriding)해서 구현한 Student 클래스의 함수가 호출된다.
클래스 변수와 객체 변수
https://junstar92.tistory.com/65
class Shop:
def __init__(self): # 자식 클래스(HairShop, Restaurant)에도 초기화되는 객체 필드
self.reserve_list = []
def reserve(self, customer): # self가 인자로 들어가기 때문에 객체별로 생성되어야 하는 메소드 (객체별로 reserve_list 다름)
self.reserve_list.append(customer)
return True
class Restaurant(Shop):
def __init__(self): # Restaurant 클래스의 인스턴스 생성 시 자동으로 상속되지만 명시함
super().__init__()
def reserve(self, customer):
if customer.num_of_people >= 2 and customer.num_of_people <= 8:
count = 0
for i in self.reserve_list:
if i.time == customer.time:
count += 1
if count <= 1:
super().reserve(customer)
return True
return False