객체 지향 프로그래밍은 실제 세계의 모습을 프로그램 코드에 그대로 반영하기 위하여 만들어졌습니다. 과거에 시뮬레이션 프로그램을 구현하기 위해 현실 세계의 것들을 프로그래밍 언어로 표현할 필요가 있었고, 이를 위하여 객체지향 프로그래밍 패러다임이 등장하게 됩니다.
객체지향 프로그래밍 패러다임에서는 현실 세계의 물건들을 객체(object)
로 표현하고, 객체를 만들기 위한 틀을 클래스(class)
로 정의합니다. 기능과 특성의 모음을 변수와 메소드로서 클래스(class)라는 캡슐에 넣고, 클래스를 실체화(instance)하면 객체(object)를 만들 수 있는 것입니다.
사실 객체지향은 프로그래밍 입문자들이 종종 힘들어하는 장벽 중 하나입니다. '클래스가 어려워요'라는 생각은, 실제로 프로그래밍 언어의 요소로서 어려운 게 아니라 객체지향 프로그래밍 패러다임에 대한 이해가 부족하기 때문이므로 패러다임 자체에 대한 학습을 조금 더 하는 것이 좋습니다.
Python의 객체지향
Python은 객체지향을 지원하는 멀티 패러다임 언어입니다. 아래는 Python 클래스의 가장 간단한 예입니다.
class FishBread: | |
pass |
아무런 기능도 갖고 있지 않고, 객체지향으로 따지면 정말 '틀'만을 가지고 있는 클래스입니다. 그러나 객체를 생성하는 기능은 가지고 있습니다.
class FishBread: | |
pass | |
fish_bread = FishBread() | |
fish_bread_2 = FishBread() |
FishBread()
의 결과값을 돌려받은 fish_bread
와 fish_bread_2
가 객체입니다. 붕어빵을 의미하는 'FishBread'라는 틀(클래스)을 이용해 붕어빵 객체 두 개가 생성되었네요.
생성자와 소멸자, 필드와 메소드
생성자는
객체가 생성될 때 호출되는 메소드이며, 소멸자
는 객체가 삭제될 때 호출되는 메소드입니다. 그리고 클래스 필드
는 모든 객체가 공유하는 필드이고, 인스턴스 필드
는 각각의 객체가 별도로 가지는 필드입니다. 생성자와 소멸자, 클래스 필드와 인스턴스 필드, 메소드를 모두 가지고 있는 클래스를 정의해 보겠습니다.
class Account: | |
num_of_account = 0 | |
# 클래스 변수 | |
# 모든 객체가 공유 | |
# 생성자 | |
def __init__(self, id, pw): | |
self.id = id | |
self.pw = pw | |
# 인스턴스 변수 | |
# 각각의 객체가 별도로 가짐 | |
Account.num_of_account += 1 | |
# 클래스 변수의 접근 | |
# 소멸자 | |
def __del__(self): | |
Account.num_of_account -= 1 | |
# 메소드 | |
def login(self, id, pw): | |
if self.id == id and self.pw == pw: | |
return True | |
else: | |
return False | |
acc1 = Account('idid', 'pwpw') | |
acc2 = Account('city7310', 'PlanB') | |
# 객체 생성 | |
print(Account.num_of_account) | |
# 클래스 변수 접근 | |
# 2 출력 | |
print(acc1.login('idid', 'pwpw')) | |
print(acc2.login('hello', 'pw')) | |
# 객체.메소드() 형태로 호출 시 self에는 해당 객체가 자동으로 들어간다 | |
# 아래와 같이 함수를 호출할 수도 있음 | |
print(Account.login(acc1, 'idid', 'pwpw')) | |
# Class level로 호출하며 객체를 명시적으로 전달 | |
del acc1 | |
# 수동으로 소멸자를 불러내는 부분.(acc1.__del__()과 같음) 객체의 참조가 0이 되면 GC에 의해 자동으로 call됨 | |
print(Account.num_of_account) | |
# 1 출력 |
생성자는 __init__
메소드로 정의(7번 라인)하고, 소멸자는 __del__
메소드로 정의(17번 라인)합니다. 각각 객체가 생성(27, 28번 라인)되고, 삭제(43번 라인)될 때 호출됩니다. 인스턴스 필드는 self.[variable]
처럼 접근(8, 9번 라인)하고, 클래스 필드는 [Class].[variable]
처럼 접근(13번 라인)합니다.
한가지 특별한 점은 self
변수인데, 이는 객체 자신을 나타내며 Java의 this
와 같습니다. Java와는 다르게 메소드에 self
를 명시한다는 점이 조금 특별합니다. 객체에서 메소드 호출 시 자동으로 해당 객체가 self에 채워지며, 이는 Class level로 메소드를 호출하며 객체를 넘겨줄 수도 있다는 것(40번 라인)입니다.
어렵지만, 객체지향이라는 패러다임에 익숙해지길 바라는 수밖에 없습니다.
Python의 모든 요소는 객체
Python의 모든 요소(int, str, bytes, list, tuple과 같은 데이터 타입, 함수 등)는 객체입니다. 따라서 저마다의 인스턴스 필드와 메소드들이 존재합니다.
s = 'PlanB' | |
print(s.isupper(), s.islower()) | |
# False False | |
# 대문자로만 이루어져 있는지 / 소문자로만 이루어져 있는지 | |
print(s.upper(), s.lower()) | |
# 'PLANB' 'planb' | |
# 모두 대문자로 만들어 반환 / 모두 소문자로 만들어 반환 | |
print(s.replace('an', 'aa')) | |
# PlaaB | |
# 문자열에 등장하는 모든 'an'을 'aa'로 만들어 반환 | |
print(s.count('a')) | |
# 1 | |
# 문자열에 속해 있는 'a'의 갯수 | |
print(s.split('a')) | |
# ['Pl', 'nB'] | |
# 'a'를 기준으로 잘라서 리스트로 반환 |
l = [1, 2, 3, 4, 5] | |
# -- 추가 -- | |
l.append(6) | |
# 맨 끝에 값 추가 | |
# -> [1, 2, 3, 4, 5, 6]이 됨 | |
l.insert(3, 5) | |
# 3번 인덱스에 값 삽입 | |
# -> [1, 2, 3, 5, 4, 5, 6]이 됨 | |
# -- 찾기 -- | |
print(l.count(5)) | |
# 2 | |
# 리스트에 속해 있는 5의 갯수 | |
print(l.index(5)) | |
# 3 | |
# 리스트에서 5가 가장 먼저 등장하는 위치 | |
# -- 제거 -- | |
print(l.pop()) | |
# 6 | |
# 리스트의 -1번 인덱스의 값을 반환하고 제거 | |
# -> [1, 2, 3, 5, 4, 5]가 됨 | |
l.remove(5) | |
# 리스트에서 가장 먼저 등장하는 5를 제거 | |
# -> [1, 2, 3, 4, 5]가 됨 | |
l.clear() | |
# 리스트 clear | |
# -- 정렬과 뒤집기 -- | |
l = [1, 2, 5, 4, 3 | |
l.sort() | |
# 오름차순 정렬 | |
# -> [1, 2, 3, 4, 5] | |
l.sort(reverse=True) | |
# 내림차순 정렬 | |
# -> [5, 4, 3, 2, 1] | |
l.reverse() | |
# 리스트 뒤집기 | |
# -> [1, 2, 3, 4, 5] |
t = 1, 2, 3, 4, 5 | |
print(t.count(5)) | |
# 1 | |
# 튜플에 속해 있는 5의 갯수 | |
print(l.index(5)) | |
# 4 | |
# 튜플에서 5가 가장 먼저 등장하는 위치 |
d = {1: 10, 2: 20} | |
print(d.get(1)) | |
# 10 | |
# 인자로 전달된 값을 key로 하여 value 반환 | |
print(d.get(3)) | |
# None | |
# 존재하지 않는 key라면 None 반환 | |
print(d.get(3, 'empty')) | |
# 'empty' | |
# key가 존재하지 않을 경우 반환되는 기본값을 지정해줄 수 있음 | |
print(d.keys(), list(d.keys())) | |
# dict_keys([1, 2]) [1, 2] | |
# 딕셔너리의 key들을 리스트로 반환 | |
print(d.values(), list(d.values())) | |
# dict_values([10, 20]) [10, 20] | |
# 딕셔너리의 value들을 리스트로 반환 | |
print(d.items(), list(d.items())) | |
# dict_items([(1, 10), (2, 20)]) [(1, 10), (2, 20)] | |
# 딕셔너리의 요소들을 [(key, value), (key, value), ...] 형태로 반환 | |
d.update({1: 15, 3: 30}) | |
# 딕셔너리 update | |
# -> d = {1: 15, 2: 20, 3: 30} | |
d.clear() | |
# 딕셔너리 clear |
'Python 계열 > Python 레거시 글' 카테고리의 다른 글
[Python] 언더스코어와 magic method (0) | 2018.07.01 |
---|---|
[Python] 클래스의 상속 (0) | 2018.06.30 |
[Python] 빌트인 함수 (0) | 2018.06.28 |
[Python] 값으로서의 함수와 lambda (0) | 2018.06.27 |
[Python] docstring (0) | 2018.06.26 |