직관적으로 클래스를 이해하는데 보통 붕어빵틀과 붕어빵을 예시로 든다.
가장 간단한 예시로,
class frame:
pass
adzuki = frame()
cream = frame()
기본적인 클래스의 구조는 다음과 같다.
class 클래스명()
[변수 1] # 클래스 변수
[변수 2]
def 함수1(self, 인자1, 인자2, ......, 인자n) # 메서드
<코드 블록>
...
def 함수2(self, 인자1, 인자2, ......, 인자n)
<코드 블록>
...
예시로 만들어 보면,
class Bicycle():
def move(self, speed): #self는 자기 인스턴스를 인식하는 것임, my_bicycle을 인식하는 것
print("자전거: 시속 {0}킬로미터 전진".format(speed))
def turn(self, direction):
print("자전거: {0}회전".format(direction))
def stop(self):
print("자전거 {0}, {1}: 정지 ".format(self.wheel_size, self.color))
my_bicycle = Bicycle() # my_bicycle라는 Bicycle의 인스턴스 생성
my_bicycle.wheel_size = 26 # 인스턴스의 속성을 생성하고 값을 넣음
my_bicycle.color = "black"
my_bicycle.move(30)
my_bicycle.turn('좌')
my_bicycle.stop()
자전거: 시속 30킬로미터 전진
자전거: 좌회전
자전거(26, black): 정지
my_bicycle.move(30)
self
는 특별한 의미를 가진다. move 메서드에는 self, speed 총 2개의 매개변수가 필요한데 실제로는 1개의 값만 전달했다.my_bicycle.move(30)
처럼 호출하면 move 메서드의 첫 번째 매개변수 self에는 move 메서드를 호출한 객체 my_bicycle
이 자동으로 전달되기 때문이다. def stop(self, wheel_size, color):
self.wheel_size = wheel_size
self.color = color
print("자전거 {0}, {1}: 정지 ".format(self.wheel_size, self.color))
my_bicycle.stop(26, 'black)
자전거(26, black): 정지
my_bicycle.stop(26, 'black)
처럼 호출하면 stop 메서드의 매개변수 wheel_size
, color
에는 각각 26과 'black'이 전달되어 다음과 같이 해석된다.self.wheel_size = 26
self.color = 'black'
self
는 전달된 객체 my_bicycle
이므로 다음과 같이 해석된다.my_bicycle.wheel_size = 26
my_bicycle.color = 'black'
my_bicycle.wheel_size = 26
이 실행되면 my_bicycle
객체에 객체변수 wheel_size
가 생성되고 값 26이 저장된다. 마찬가지로 my_bicycle.color = 'black'
이 실행되면 my_bicycle
객체에 객체변수 color
가 생성되고 'black'이 저장된다. 확인을 해보면,
my_bicycle = Bicycle()
my_bicycle.stop(26,'black')
print(my_bicycle.wheel_size)
print(my_bicycle.color)
자전거 26, black: 정지
26
black
객체 my_bicycle에 객체변수 wheel_size
와 color
가 생성된 것을 알 수 있다.
my_bicycle = Bicycle()
your_bicycle = Bicycle()
my_bicycle.stop(26,'black')
your_bicycle.stop(30,'red')
wheel_size
를 생성한다고 했을 때 your_bicycle 객체의 객체 변수 wheel_size
에는 30의 값이 저장되는 것을 확인할 수 있다.wheel_size
가 30으로 변할지 그대로 유지되는지 확인을 해보면 그대로 유지되는 것을 확인할 수 있다.기존 Bicycle 클래스에 count라는 연산 기능을 하는 메서드를 추가했다.
class Bicycle():
def move(self, speed):
print("자전거: 시속 {0}킬로미터 전진".format(speed))
def turn(self, direction):
print("자전거: {0}회전".format(direction))
def stop(self, wheel_size, color):
self.wheel_size = wheel_size
self.color = color
print("자전거 {0}, {1}: 정지 ".format(self.wheel_size, self.color))
def count(self):
result = self.wheel_size * 2
return result
my_bicycle = Bicycle()
my_bicycle.stop(26, 'black')
print(my_bicycle.count())
my_bicycle.stop
메서드를 실행하면서 self.wheel_size
가 26으로 이미 설정되었고 count 함수에서 곱하기 2를 해주었기 때문에 52가 출력되는 것을 확인할 수 있다.
self.wheel_size
생성되기 때문이다. 이렇게 객체에 초깃값을 설정해야 할 필요가 있을 때 기본적으로 생성자를 구현하는 것이 더 안전한 방법이다.__init__
을 사용한다!my_bicycle = Bicycle(20,'blue')
class Bicycle():
def __init__(self, wheel_size, color):
self.wheel_size = wheel_size
self.color = color
def move(self, speed):
print("자전거: 시속 {0}킬로미터 전진".format(speed))
def turn(self, direction):
print("자전거: {0}회전".format(direction))
def stop(self, wheel_size, color):
self.wheel_size = wheel_size
self.color = color
print("자전거 {0}, {1}: 정지 ".format(self.wheel_size, self.color))
def count(self):
result = self.wheel_size * 2
return result
클래스의 상속은 어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만드는 것이다. 보통 상속은 기존 클래스를 변경하지 않고 기능을 추가하거나 기존 기능을 변경하려고 할 때 사용한다. 기존 클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않는 상황이 발생하기 때문에 상속을 사용하는 것이다.
class Auto(Bicycle): # 이렇게 하면 Auto클래스가 Bicycle 클래스를 상속 했으므로 모든 기능을 사용할 수 있음
def count4(self):
result = self.wheel_size * 4
return result
상속받은 클래스에 메서드를 쓰면서 오류가 생기거나, 혹은 메서드를 상황에 맞게 변경을 해주고 싶다면 자녀 클래스에서 부모 클래스에 있는 메서드를 동일한 이름으로 다시 만드는 것을 메서드 오버라이딩
이라고 한다. 이렇게 메서드를 오버라이딩하면 부모 클래스의 메서드 대신 오버라이딩한 메서드가 호출된다.
class Auto(Bicycle): # 이렇게 하면 Auto클래스가 Bicycle 클래스를 상속 했으므로 모든 기능을 사용할 수 있음
def count(self): # 부모 클래스인 Bicycle의 count 메서드를 변경해서 Auto 클래스에 적용!
result = self.wheel_size ** 2
return result
클래스 변수는 클래스 안에 선언하여 생성하고 객체들을 통해서도 클래스 변수를 사용할 수 있다. 만약 클래스 변수를 변경하면, 클래스로 만든 객체들을 통해서도 모두 클래스 값이 변경되는 것을 알 수 있다.
class Bicycle():
today='월'
pass
print(Bicycle.today) # 월이 출력된다.
a = Bicycle()
print(a.today) # 월이 출력된다.
Bicycle.today = '화'
print(a.today) # 화가 출력된다.
class Car():
instance_count = 0 # 클래스 변수 생성
def __init__(self, size, color):
self.size = size # 인스턴스 변수 생성 및 초기화
self.color = color # 인스턴스 변수 생성 및 초기화
Car.instance_count = Car.instance_count +1 # 클래스 변수 이용, '클래스명.변수명' 형식으로 접근
print("자동차 객체의 수:{0}".format(Car.instance_count))
def move(self, speed):
self.speed = speed
print("자동차({0} & {1})가 ".format(self.size, self.color), end='')
print("시속 {0}킬로미터로 전진".format(self.speed))
def auto_cruise(self):
print("자율 주행 모드")
self.move(self.speed)
# 정적 메서드, 클래스에 직접 접근할 수 있는 메서드
@staticmethod
def check_type(model_code): # check_type라는 함수를 선언했고 이건 인스턴스에 종속하는 함수가 아님
if(model_code >= 20):
print("이 자동차는 전기차입니다.")
elif(10 <= model_code < 20):
print("이 자동차는 가솔린차입니다.")
else:
print("이 자동차는 디젤차입니다.")
# 클래스 메서드, 외부의 영향없이 클래스만의 변수들, 함수들을 쓰려고!
# cls를 쳐주면서 Car라는 클래스의 것들을 맘대로 쓸 수 있다.
@classmethod
def count_instance(cls):
print("자동차 객체의 개수: {0}".format(cls.instance_count))
# 클래스 상속
class Truck(Car):
#클래스 오버라이딩
def auto_cruise(self):
print("자율 주행 모드 시작하겠습니다.")
self.move(self.speed)