BASEMENT
Python 4주차 - 1 본문

클래스 (Class)
1. 객체 지향 프로그래밍
클래스 기반의 프로그램을 작성
- 클래스는 속성과 메서드를 하나로 묶어서 처리하는 캡슐화 성질을 가짐
- 사용자 정의를 통해 새로운 객체(자료형)를 만들어서 사용 -> 인스턴스(instance) 생성
객체 지향의 성질
- 객체 또는 인스턴스를 생성한 후 사용
- 상속성 : 기존 class의 기능들을 다른 class에 상속 가능
- 다형성 (오버로딩, 오버라이딩) : 상속받은 기능 수정 가능
2. 클래스
클래스의 구조
- 현실 세계의 사물을 컴퓨터 안에서 구현하려고 고안된 개념
- class 키워드 사용
- 클래스 이름은 첫글자를 대문자로 지정 (함수와 구별 용이)
- self 매개변수 : 각 인스턴스가 클래스의 속성과 메서드 등에 접근할 수 있게 해주는 권한 역할
클래스의 예 - 자동차 클래스
class 자동차:
# 자동차의 속성 -> 변수 생성 : 필드 (field)
색상
속도
# 자동차의 기능 -> 함수 생성 / 클래스 내의 함수 : 메서드(method)
속도 올리기()
속도 내리기()
class Car의 인스턴스를 생성하여 실행시키기
* self
인스턴스의 정보가 들어가는 매개변수
클래스 외부에서 필드를 인스턴스를 통해 사용하기 위해서 꼭 필요함
id를 이용한 self의 의미 확인
인스턴스를 사용하지 않고 클래스 메서드로도 사용 가능 -> 잘 사용하진 않음
3. 생성자 (Constructor)
- 클래스 인스턴스 생성 시 자동으로 호출되는 메서드
- 인스턴스 생성 시 필드(변수) 등의 초기값 설정
- 생성자 기본 : Special Method 또는 Magic Method
- 기본형태 : __init__(self)
예제
Point 클래스는 생성자를 통해 (x,y) 좌표를 입력
setx(x), sety(y) 메서드를 통해 x좌표와 y좌표를 따로 입력
get() 메서드를 호출하면 튜플로 구성된 (x,y) 좌표 반환
movexy(dx,dy) 메서드는 현재 좌표를 dx, dy만큼 이동
4. 네임스페이스 (namespace)
변수가 객체를 바인딩할 때 그 둘 사이의 관계를 저장하고 있는 공간을 의미함
ex) a = 2 -> #2 라는 객체가 저장된 주소를 a가 가지고 있으며 이러한 연결 관계가 저장된 공간 (네임스페이스)
- 파이썬 클래스는 하나의 네임스페이스를 가짐
- dir() 함수로 객체에 정의된 식별자(함수, 변수 등) 확인
- __dict__ : 해당되는 개체의 속성들을 딕셔너리형태로 확인
- 클래스가 정의되면 독립적인 네임스페이스가 생성됨
class Country:
local = "Seoul"
def addr(self, *others): # *others : 가변 매개변수
self.local, self.gu, self.load = others
if __name__ == "__main__":
me = Country()
print(Country.__dict__)
print(me.__dict__)
me.addr('부산','해운대','해운대로')
print(me.__dict__)
print(f'{me.local}{me.gu}{me.load}')
5. 인스턴스 변수와 클래스 변수
1) 인스턴스 변수
- 인스턴스 생성 시 사용할 수 있는 변수
- 클래스 내에 선언된 인스턴스 변수는 실제 공간이 할당되지 않음 -> 인스턴스 생성 시 공간 할당됨
- 인스턴스 변수 예
class Car:
def __init__(self):
self.color = ""
self.speed = 0
redCar = Car() # 인스턴스 생성. color, speed 공간 할당
redCar.color = "red"
redCar.speed = 100
2) 클래스 변수
- 클래스 내에 저장공간이 할당된 변수
- 한 클래스의 여러 인스턴스들 사이의 전역변수 역할 -> 클래스 변수 공간을 공동으로 사용
- 클래스 변수 생성은 인스턴스 변수 생성과 동일
- 사용 시 클래스명.클래스변수명 or 인스턴스.클래스변수명
클래스 변수 사용 예
class Country:
local = "서울" # 클래스 변수
print(f'id of local: {id(local)}')
def addr(self, *others):
self.gu, self.load = others
print(f'id of self.local: {id(self.local)}') # 인스턴스 필드가 없으므로 클래스 변수와 같음
if __name__ == "__main__":
me = Country()
you = Country()
me.addr('영등포구', '선유로')
print(f'id of me.local: {id(me.local)}') # 클래스 변수와 같음
print(f'id of you.local: {id(you.local)}') # 클래스 변수와 같음
print(f'id of me.local: {id(Country.local)}') # 클래스 변수와 같음
클래스 변수 사용 예
6. 클래스 상속 (Inheritance)
상속의 개념
- 기존 클래스(부모클래스)에 있는 필드 및 메서드 등의 성질을 그대로 물려받은 새로운 클래스(자식클래스)를 생성
상속받는 클래스 생성 과정
- 공통된 내용을 담은 클래스 생성 (부모 클래스)
- 공통된 내용 + 변형된 내용을 담은 클래스 생성 (자식 클래스)
- ex) 차의 공통된 성질로 구성된 자동차 클래스 생성 -> 차의 공통성질
- + 차 종류에 따른 차별화 성질로 구성된 승용차, 트럭, 버스 등의 클래스 생성
자식 클래스에 별도의 생성함수가 부모 클래스의 생성함수 이용 시
super(). 사용
7. 메서드 오버라이딩 (Overriding)
상위 클래스의 메서드를 서브 클래스에서 재정의하는 것
ex) 속도 올리기에서 승용차 클래스는 150이상 불가한 경우
__init__ 메서드 오버라이딩 예제
upSpeed 메서드 오버라이딩 적용된 경우 예제
Car -> Sedan -> Sona 클래스 생성 (상속의 상속)
8. 접근성 (access)
객체의 정보를 볼 수 있는 레벨을 조절 -> 객체의 정보 접근을 숨기는 것
캡슐화 (encapsulation) 또는 정보 은닉 (information hiding)
- 객체의 매개 변수 인터페이스만 명확하게 알면 사용
파이썬은 일반 객체지향 언어가 가지는 자원(필드, 메서드) 접근 권한에 대한 접근 지정자가 없음
-> public, private, protected등
자원 접근 권한에 대한 규칙으로 대신함
- 자원 이름 앞에 _ 또는 __ 를 사용하여 접근권한을 명시적으로 표시
- _ (single underscore) : protected, 클래스 내 또는 상속받은 클래스 내에서 사용
- __ (double underscore) : private, 선언된 클래스 내에서만 사용 (자식 클래스에서도 사용 불가)
single underscore 예제
실제적으로는 외부 접근 가능하나, 코드 작성자는 외부 접근 코드를 작성하지 않음
double underscore 예제
상속된 자식 클래스 및 외부에서의 접근 불가, 오류 발생
-> 실제로 private 때문에 오류가 발생하는 것은 아님. 네임 맹글링 때문에 오류 발생
9. 네임 맹글링
- 이중밑줄은 클래스 속성에 사용 시 단일밑줄과 차이점이 있음
- 네임 맹글링 적용
- 네임 맹글링 : C++에서 컴파일러가 함수, 변수 등의 이름을 임의로 지정된 규칙으로 변경하여 컴파일 하는 것
10. 가시성 (visibility)
private로 지정된 attribute를 외부에서 접근하기 위한 방법
- 외부에서 접근하기 위해서는 클래스에서 메서드를 통해 속성의 값을 가져오거나 저장하는 방식 활용
- @property 적용 (파이썬에서 @가 붙은 예약어는 데코레이터라 함)
값을 할당하고(setter), 할당된 값을 가져오는 메서드(getter) 구현을 통해 private 속성 값을 외부에서 할당하고 전달 가능
class Person:
def __init__(self):
self.__age = 0
@property
def age(self): # getter
return self.__age
@age.setter # @property의 메소드 age / @메소드.setter
def abc(self,years):
self.__age = years
korea = Person()
korea.abc = 20
print(f'{korea.age}')
@property 데코레이터 예제
11. 클래스의 특별한 메서드
1) __del__()
- 소멸자로 인스턴스 삭제 시 자동 실행
- 인스턴스 소멸 : del(인스턴스 이름)
- 특별한 동작 필요 : __del__ 함수에 작성
class Product:
def __init__(self, itemV, priceV, pieceV):
self.item = itemV
self.price = priceV
self.piece = pieceV
def cal_cost(self):
self.total = self.price*self.piece
return self.total
def __del__(self):
print("product instance extinction")
book = None
book = Product("book", 12000, 3)
print("book's cost: %d" % book.cal_cost()) # book's cost: 36000
del(book) # product instance extinction
2. __repr__()
인스턴스를 print 문으로 출력할 때 실행
class Line:
length = 0
def __init__(self, lenV):
self.length = lenV
print("%d Line 인스턴스 생성" % self.length) # 200 Line 인스턴스 생성
# 400 Line 인스턴스 생성
def __repr__(self):
return '선의 길이 : ' + str(self.length)
myL1, myL2 = None, None
myL1 = Line(200)
myL2 = Line(400)
print(myL1) # 선의 길이 : 200
print(myL2) # 선의 길이 : 400
3. __add__()
인스턴스 사이의 덧셈 작업이 일어날 때 실행
class Line:
length = 0
def __init__(self, lenV):
self.length = lenV
print("%d Line 인스턴스 생성" % self.length)
def __add__(self, other):
return self.length + other.length
myL1, myL2 = None, None
myL1 = Line(200)
myL2 = Line(400)
print('두 선의 길이 합 : ', myL1+myL2) # 두 선의 길이 합 : 600
4. 비교 - __lt__(), __le__(), __gt__(), __ge__(), __eq__(), __ne__()
인스턴스 사이의 비교 연산자를 사용할 때 호출
class Line:
length = 0
def __init__(self, lenV):
self.length = lenV
print("%d Line 인스턴스 생성" % self.length)
def __lt__(self, other):
return self.length < other.length
def __eq__(self, other):
return self.length == other.length
myL1, myL2 = None, None
myL1 = Line(200)
myL2 = Line(400)
if myL1 < myL2: # myL2의 선분이 더 깁니다
print('myL2의 선분이 더 깁니다')
elif myL1 == myL2:
print('myL1 == myL2 입니다')
else:
print('myL1의 선분이 더 깁니다')
12. 추상 메서드
오버라이딩을 위한 부모 클래스 내의 빈 껍질 메서드
반드시 자식 클래스 내에서 오버라이딩을 해야 함
class Parents:
def method(self):
pass # pass : 함수 미정일 때 오류를 방지하기 위함
class Child1(Parents):
def method(self):
print("Child1에서 method를 오버라이딩")
class Child2(Parents):
def method(self):
print("Child2에서 method를 오버라이딩")
sub1 = Child1()
sub2 = Child2()
sub1.method() # Child1에서 method를 오버라이딩
sub2.method() # Child2에서 method를 오버라이딩
class Parents:
def method(self):
raise NotImplementedError() # raise : 예외를 강제로 발생시킴
class Child1(Parents):
def method(self):
print("Child1에서 method를 오버라이딩")
class Child2(Parents):
pass
sub1 = Child1()
sub2 = Child2()
sub1.method()
sub2.method() # Child2 자식클래스를 생성하지 않아서 오류를 발생시킴
13. 클래스 다중상속
클래스 다중 상속시, 먼저 작성된 클래스의 생성자 함수를 실행함
class Car:
speed = 0
def __init__(self, color, shape):
self.color = color
self.shape = shape
print("{}와 {}의 차입니다".format(self.color, self.shape))
def speedup(self, speed):
self.speed += speed
def speeddown(self, speed):
self.speed -= speed
class SemiSelfCar:
def __init__(self, option):
self.option = option
print("%d 옵션입니다" % self.option)
def ADAS(self, control):
self.control = control
if self.control == 'stop':
print("Step on the brake")
elif self.control == 'accel':
print("Step on the accel")
else:
print("Control fail")
class SelfDrivingCar(Car, SemiSelfCar): # 생성자함수 : Car의 생성자 함수
def auto_map(self):
print("printing auto_map")
def auto_run(self):
print("{} 속도로 자율 주행합니다".format(self.speed))
auto1 = SelfDrivingCar("green", "Sedan")
auto1.speedup(30)
auto1.auto_run() # green와 Sedan의 차입니다
# 30 속도로 자율 주행합니다
# 예제 - 클래스 내 클래스
# Play 클래스가 삭제되면 Customer 클래스 오류 발생 -> 클래스 종속 관계
class Customer:
def __init__(self, name, num):
self.name = name
self.num =num
def book(self, play, place):
self.play = Play(play, place) # Customer 클래스 내에 Play 클래스 사용
def classPoint(self, point, name):
self.play.p_point(point)
class Play:
points = {}
def __init__(self, name, place):
self.p_name = name
self.place = place
def p_point(self, point):
if self.p_name in Play.points:
Play.points[self.p_name] += point
else:
Play.points[self.p_name] = point
def point_print(self):
print(f'{self.p_name}의 평점 : {Play.points[self.p_name]}')
if __name__ == '__main__':
c1 = Customer('Gildong', '123')
c1.book('Rent', 'ArtCenter')
c1.classPoint(5, 'Rent')
c2 = Customer('Jane', '124')
c2.book('Rent', 'ArtCenter')
c2.classPoint(3, 'Rent')
c3 = Customer('Yuna', '125')
c3.book('Dracula', 'Sejong')
c3.classPoint(4, 'Dracula')
p1 = Play('Rent', 'ArtCenter')
p1.point_print() # Rent의 평점 : 8
p2 = Play('Dracula', 'Sejong')
p2.point_print() # Dracula의 평점 : 4
'Programming > Python' 카테고리의 다른 글
Python 5주차 (0) | 2020.07.26 |
---|---|
Python 4주차 - 2 (0) | 2020.07.12 |
Python 3주차 - 2 (0) | 2020.07.12 |
Python 3주차 - 1 (0) | 2020.07.12 |
Python 2주차 - 2 (0) | 2020.07.11 |