객체 지향 : 실제 세계를 모델링하여 프로그램을 개발하는 개발 방법론
Class
- 변수와 함수를 묶어서 코드를 작성하는 방법
- 객체 지향을 구현하는 문법
- 사용법 : 클래스 선언(코드 작성) -> 객체 생성(메모리 사용) -> 메소드 실행(코드 실행)
- 실제 세계에 비유 : 설계도 작성 -> 제품 생산 -> 기능 사용
- 통상 클래스는 pascal case(upper camel case), 변수와 함수는 snake case로 작성
관련용어 : class, self, special method, 상속, super, getter-setter, mangling 등
코드를 통해 알아보자.
1. 클래스 선언 : 코드 작성 - 계산기 클래스
# 계산기 설계 : number1, number2를 이용해서 덧셈, 뺄셈 기능 구현 class Calculator: number1, number2 = 1, 2 def plus(self): return self.number1 + self.number2 def minus(self): return self.number1 - self.number2
2. 객체 생성 : 메모리 사용
# Calculator 객체 2개 생성 calc1 = Calculator() calc2 = Calculator()
객체를 생성한 후 dir() 함수를 통해 객체에 들어 있는 변수, 함수 목록을 출력
# dir() : 객체에 들어 있는 변수 목록을 출력 lst = [var for var in dir(calc2) if var[0] != '_'] print(lst) # 실행 결과 ['minus', 'number1', 'number2', 'plus']
각 객체에 변수 값 확인
print(calc1.number1, calc1.number2, calc2.number1, calc2.number2) # 실행 결과 1 2 1 2
3. 메소드 실행 : 코드 실행
print(calc1.plus(), calc2.minus()) # 실행 결과 3 -1
각 객체의 plus() 메소드와 minus() 메소드 실행 결과 1+2, 1-2 값이 잘 출력됨을 알 수 있다.
이번에는 calc1의 변수 number1을 수정한 후 다시 메소드를 실행해 보자.
# 객체의 변수 수정 calc1.number1 = 20 print(calc1.number1, calc1.number2, calc2.number1, calc2.number2) print(calc1.plus(), calc2.plus()) # 실행 결과 20 2 1 2 22 3
변수 값이 수정된 것을 확인하고 다시 실행한 결과 20+2와 1+2 값이 출력되었다.
self : 객체 자신을 의미
- calc1.plus()에서 self == calc1 이므로 self.number1 + self.number2는 calc1.number1 + calc1.number2를 의미
금액 초기값이 10000원인 계좌 클래스를 생성
special method __init__()과 default parameter를 활용했다.
계좌 생성할 때 괄호 안을 비우면 10000원이 default이며, 값을 넣으면 그 값이 초기값으로 설정된다.
입금, 출금 결과 계좌 잔액을 확인할 수 있다.
코드를 직접 수정하며 금액을 바꾸어 보고 실습할 수 있다.
special method __add__()
먼저 코드를 보면
d1, d2, d3, d4 = 1, 2, '3', '4' print(d1.__add__(d2)) # int 클래스의 __add__() 메소드 print(d3.__add__(d4)) # str 클래스의 __add__() 메소드 # 실행 결과 3 34
두 경우 모두 __add__() 메소드를 사용했지만 다른 연산을 하게 된다.
이처럼 같은 이름의 메소드를 사용하더라도 데이터 타입에 따라서 수행되는 연산이 다를 수 있다.
__add__() 메소드를 사용하지만 뺄셈 연산이 수행되는 객체를 생성해 보자
# __add__() 메소드를 사용하지만 뺄셈 연산이 수행되는 객체 생성 class Number: def __init__(self, data): self.data = data def __add__(self, number): return self.data - number num1 = Number(10) num2 = Number(3) print(num1 + 5) print(num2 + 5) # 실행 결과 5 -2
num1 + 5가 15, num2 + 5가 8의 결과가 아닌 뺄셈의 결과를 확인할 수 있다.
상속 : 다른 클래스의 변수(메소드)를 가져와서 사용하는 방법
업그레이드되는 3가지 버전의 Phone을 구현해 보자
Phone1 기능 1개 : call
Phone2 기능 2개 : call, send_msg
Phone3 기능 3개 : call, send_msg, internet
class Phone1: def call(self): print('calling!') class Phone2: def call(self): print('calling!') def send_msg(self): print('send_msg!') class Phone3: def call(self): print('calling!') def send_msg(self): print('send_msg!') def internet(self): print('internet!')
중복되는 코드들이 눈에 보인다. 이럴 경우 유용하게 사용되는 것이 상속이다.
# 상속을 사용 class Phone1: def call(self): print('calling!') class Phone2(Phone1): # Phone1 상속 def send_msg(self): print('send_msg!') class Phone3(Phone2): # Phone2 상속 def call(self): # overide print('video calling!') def internet(self): print('internet!')
#객체 생성 phone1 = Phone1() phone2 = Phone2() phone3 = Phone3()
phone1.call() phone2.call() phone2.send_msg() phone3.call() phone3.internet() # 실행 결과 calling! calling! send_msg! video calling! internet!
상속받은 클래스의 기능을 물려받는 개념이다. Phone3의 경우 call 메소드를 다시 작성하여 다른 동작을 하도록 바꿨다.
이를 override라고 한다.
다중 상속 : 여러 클래스를 상속받는 것 - 파이썬의 특징
파이썬 클래스는 동시에 여러 클래스를 상속받을 수 있다.
먼저 Human (걷기), Korean (김치 먹기), Indian(카레 먹기) 클래스를 선언한다.
class Human: def walk(self): print('walking!') class Korean: def eat(self): print('eat kimchi!') class Indian: def eat(self): print('eat curry!')
이후 코딩을 하는 한국인 Jin과 영어를 하는 인도인 Anchel 클래스를 선언한다.
# 코딩을 하는 한국인 Jin과 영어를 하는 인도인 Anchel 클래스 선언 # Human -> Korean -> Jin 순서로 상속 class Jin(Korean, Human): # 상속 순서도 중요 def skill(self): print('coding') # Human -> Indian -> Anchel class Anchel(Indian, Human): def skill(self): print('speak english!')
Jin, Anchel 객체를 생성한 후 메소드를 실행해 보자.
# Jin, Anchel 객체 생성 jin = Jin() anchel = Anchel() jin.walk() anchel.walk() jin.eat() anchel.eat() jin.skill() anchel.skill() # 실행 결과 walking! walking! eat kimchi! eat curry! coding speak english!
한국인과 인도인을 잘 구현하였다.
데코레이터(decorator) : 함수에서 중복되는 코드를 빼서 데코레이터 함수로 만든다 - 파이썬의 특징
- 원래 있던 함수에 새로운 기능을 추가한 함수로 변경할 때 주로 사용
코드를 보고 어느 부분이 중복되는지 확인, 데코레이터 사용 전후를 비교해 보자
# 데코레이터 사용 전 def func1(): print('code1') print('code2') print('code3') def func2(): print('code1') print('code4') print('code3')
# 데코레이터 사용 후 # deco 함수의 파라미터 func에 각각 func1, func2가 들어간다 # func1, func2 함수는 각각 deco 함수의 return 함수인 wrapper 함수로 변경 def deco(func): def wrapper(*args, **kwargs): print('code1') func() print('code3') return wrapper @deco def func1(): print('code2') @deco def func2(): print('code4')
@deco(@데코레이터 이름)를 함수 선언 바로 위 라인에 사용한다.
함수 실행 결과 확인
func1() func2() # 실행 결과 code1 code2 code3 code1 code4 code3
중복된 code1, code3 부분 사이에 func1, func2의 출력 결과가 잘 출력되었다.
'AI SCHOOL > TIL' 카테고리의 다른 글
[DAY 11] pandas 기초 - DataFrame, Series, Indexing 등 (2) | 2023.01.10 |
---|---|
[DAY 10] getter, setter, name mangling (0) | 2023.01.06 |
[DAY 8] parameter와 argument, lambda, list comprehension (0) | 2023.01.05 |
[DAY 7] 데이터 핸들링 스킬, 파이썬 연산자와 함수 (0) | 2023.01.05 |
[DAY 6] 코랩, 리스트와 튜플, 깊은 복사 (0) | 2023.01.05 |
댓글