일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- node.js
- mongoDB
- Git
- redis
- 유노코딩
- TiL
- 파이썬
- 자격증
- 코드잇
- 코딩테스트
- HTML
- aws
- 99클럽
- 방송대
- 개발자취업
- nestjs
- 데이터베이스시스템
- 오픈소스기반데이터분석
- 방송대컴퓨터과학과
- 프로그래머스
- 항해99
- JavaScript
- 꿀단집
- Python
- 중간이들
- Cookie
- 파이썬프로그래밍기초
- 코딩테스트준비
- 엘리스sw트랙
- CSS
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] 객체 지향 프로그래밍 in Python - 객체 지향 프로그래밍이란 본문
1. 객체 지향 프로그래밍 시작하기
• 객체 = 속성 + 행동
ex.
자동차 객체
속성 | 행동 |
색깔 : 빨강 | 시동이 걸리는 행동 |
의자 개수 : 5개 | 앞으로 나아가는 행동 |
instagram 유저 객체
속성 : 이메일주소, 비밀번호, 친구목록
행동 : 좋아요 누르기, 친구추가
객체지향 프로그래밍
프로그램을 여러 개의 독립된 객체들과 그 객체들 간의 상호작용으로 파악하는 프로그래밍 접근법
프로그램을 객체들과 객체들 간의 소통으로 바라보는 것
객체 지향적으로 설계 = 모델링(modeling)
객체 지향 프로그래밍으로 프로그램을 만들려면
1. 프로그램에 어떤 객체들이 필요할지 정한다
2. 객체들의 속성과 행동을 정한다
3. 객체들이 서로 어떻게 소통할지 정한다
2. 객체를 만드는 법
클래스와 인스턴스
• 클래스 : 객체의 틀
• 인스턴스(객체) : 틀로 만든 결과물
→ 클래스로 인스턴스를 만든다
# 클래스 이름 첫글자는 대문자
class User:
# 클래스 내용 = 속성 + 행동
pass # 아무 내용이 없음
user1 = User()
user2 = User()
user3 = User()
'''
User() : User인스턴스 생성
변수 user1이 이 User() 인스턴스를 가리킴
user 1, 2, 3은 다른 존재임
'''
인스턴스 변수
정의 | 사용하기 |
인스턴스 이름.속성이름(인스턴스 변수) = "속성에 넣을 값" user1.name = "김도비" |
인스턴스 이름.인스턴스 변수 이름 user1.email |
# 클래스 이름 첫글자는 대문자
class User:
# 클래스 내용 = 속성 + 행동
pass # 아무 내용이 없음
user1 = User()
user2 = User()
user3 = User()
user1.name = "김도비" # user1 인스턴스에 속성 추가
user1.email = "captain@codeit.kr"
user1.password = "12345"
user2.name = "나대요"
user2.email = "Nadagi@codeit.kr"
user2.password = "34245"
user3.name = "배꼽파"
user3.email = "hungry@codeit.kr"
user3.password = "14578"
# user 1, 2, 3 은 속성을 공유함
# 인스턴스 변수 : 인스턴스가 개인적으로 갖고 있는 속성 (ex. name, email, password)
print(user1.email) # captain@codeit.kr
print(user3.birthday) # 오류
인스턴스 변수를 정의하지 않고 사용하면 에러가 발생함.
인스턴스 메소드
객체
- 속성 → 변수
- 행동 → 함수 (메소드)
메소드의 종류
- 인스턴스 메소드
- 클래스 메소드
- 정적 메소드
인스턴스 메소드 : 인스턴스 변수를 사용하거나, 인스턴스 변수에 값을 설정하는 메소드
→ 클래스이름.메소드이름(인스턴스)
# 클래스 이름 첫글자는 대문자
class User:
def say_hello(some_user):
print("안녕하세요! 저는 {}입니다!".format(some_user.name))
# name : 인스턴스 변수
# say_hello : 인스턴스 메소드
user1 = User()
user2 = User()
user3 = User()
user1.name = "김도비" # user1 인스턴스에 속성 추가
user1.email = "captain@codeit.kr"
user1.password = "12345"
user2.name = "나대요"
user2.email = "Nadagi@codeit.kr"
user2.password = "34245"
user3.name = "배꼽파"
user3.email = "hungry@codeit.kr"
user3.password = "14578"
# 인스턴스 메소드 사용
User.say_hello(user1) # 안녕하세요! 저는 김도비입니다!
User.say_hello(user2) # 안녕하세요! 저는 나대요입니다!
User.say_hello(user3) # 안녕하세요! 저는 배꼽파입니다!
# 클래스에서 메소드 호출
User.say_hello(user1) # 안녕하세요! 저는 김도비입니다!
# 인스턴스에서 매소드 호출
user1.say_hello() # 안녕하세요! 저는 김도비입니다!
# user1 인스턴스가 say_hello의 첫 번째 파라미터로 자동으로 전달됨.
user1.say_hello(user1) # 오류
# user1을 추가로 한번 더 넘겨준 거로 인식해서 오류가 남.
인스턴스 메소드를 호출하는 방법 2개
1) 인스턴스로 호출하는 방법
user1.say_hello()
user1.initialize("Young", "young@codeit.kr", "123456")
2) 클래스로 호출하는 방법
User.say_hello(user1)
User.initialize(user1, "Young", "young@codeit.kr", "123456")
class User:
def say_hello(some_user):
print("안녕하세요! 저는 {}입니다!".format(some_user.name))
def login(some_user, my_email, my_password):
if some_user.email == my_email and some_user.password == my_password :
print("로그인 성공, 환영합니다.")
else:
print("로그인 실패, 없는 아이디이거나 잘못된 비밀번호입니다.")
user1 = User()
user1.name = "김도비"
user1.email = "dobby@free.co.kr"
user1.password = "1004"
User.login(user1, "dobby@free.co.kr", "1004") # 로그인 성공
user1.login(user1, "dobby@free.co.kr", "1004") # 에러
self 사용
class User:
def say_hello(self):
print("안녕하세요! 저는 {}입니다!".format(self.name))
def check_name(self, name):
# 파라미터로 받는 name이 유저(인스턴스)의 이름과 같은지 불린으로 리턴하는 메소드
return self.name == name
# 파라미터 name과 self의 name(인스턴스의 변수)이 같아도 문제가 없음.
user1 = User()
user2 = User()
user1.name = "김도비" # user1 인스턴스에 속성 추가
user1.email = "captain@codeit.kr"
user1.password = "12345"
user2.name = "나대요"
user2.email = "Nadagi@codeit.kr"
user2.password = "34245"
print(user1.check_name("김도비")) # True
# user1 인스턴스가 메소드를 호출
print(user1.check_name("홍길동")) # False
특수 메소드
파이썬에서 미리 지정한 특정 상황에 자동으로 호출되는 메소드
- __init__ : 인스턴스 생성시 자동으로 호출됨.
- __str__ : print 함수를 호출할 때 자동으로 호출됨.
__init__ 메소드
모든 인스턴스 변수를 __init__ 메소드에서 설정
user1 = User("Young", "young@codeit.kr", "123456")
1. User 인스턴스 생성
2. __init__ 메소드 자동으로 호출
3. self 에 user인스턴스, 나머지 파라미터로 받은 것들이 인스턴스 변수 초기값으로 들어감
class User:
def initialize(self, name, email, password):
self.name = name
self.email = email
self.password = password
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
user3 = User("Taeho", "taeho@codeit.kr", "123abc")
user4 = User("Lisa", "lisa@codeit.kr", "abc123")
# 출력함수
print(user1.name, user1.email, user1.password)
print(user2.name, user2.email, user2.password)
print(user3.name, user3.email, user3.password)
print(user4.name, user4.email, user4.password)
__str__ 메소드
인스턴스의 정보를 이해하기 쉬운 문자열로 나타내고 싶을 때 유용하게 사용
class User:
def __init__(self, name, email, password):
self.name = name
self.email = email
self.password = password
def say_hello(self):
print("안녕하세요! 저는 {}입니다!".format(self.name))
def __str__(self): # 던더 str (특수 메소드드)
return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.name, self.email)
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
print(user1)
# <__main__.User object at 0x7f5f4b256b90>
# 인스턴스 이름, 인스턴스가 저장된 메모리 주소
던더 메소드는 print를 호출할 때 자동으로 불림
어떤 인스턴스를 출력하면 던더 에스티알 메소드의 리턴값이 출력됨
클래스 변수
한 클래스의 모든 인스턴스가 공유하는 속성
값 읽기 | 값 설정 |
1. 클래스이름.클래스변수이름 2. 인스턴스 이름.클래스변수이름 |
1. 클래스이름.클래스변수이름 → 꼭 클래스 변수에 값을 설정할 때는 클래스 이름으로만 쓰기 |
class User:
count = 0
def __init__(self, name, email, pw):
self.name = name
self.email = email
self.pw = pw
# 클래스 변수 count가 유저 인스턴스 개수를 정확히 나타내도록 함
User.count += 1
'''
클래스 변수 생성
User.count = 1
'''
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
print(User.count) # 2
class User:
count = 0
def __init__(self, name, email, pw):
self.name = name
self.email = email
self.pw = pw
User.count += 1
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
user3 = User("Taeho", "taeho@codeit.kr", "123abc")
user4 = User("Lisa", "lisa@codeit.kr", "abc123")
print(User.count) # 클래스.클래스변수
print(user1.count) # 인스턴스.클래스변수수
print(user2.count)
print(user3.count)
# 둘다 4라고 제대로 출력됨
user1.count = 5 # user1의 클래스변수만 변경
print(user1.count) # 5라고 바뀜
'''
이 코드는 클래스변수를 설정하는 것 (X)
같은 이름의 인스턴스를 생성해서 인스턴스 변수를 추가함 (O)
→ 같은 이름의 클래스변수 vs 인스턴스 변수
→ 인스턴스 변수가 읽어짐
→ 헷갈리니까 클래스 변수에 값 설정할 때는 "클래스 이름으로만" 설정!
'''
데코레이터(decorator)
함수의 호출 전후에 추가 작업을 수행하도록 하여 기존 함수의 동작을 확장
def print_hello():
print('안녕하세요!')
def add_print_to(original):
def wrapper():
print('함수 시작') # 부가기능
original()
print('함수 끝') # 부가기능
return wrapper
# 어떤 함수를 받아서 또 다른 함수를 리턴함
add_print_to(print_hello) # ----> 데코레이터 함수
# add_print_to 내에서는 original이랑 print_hello랑 똑같은 함수
# wrapper 함수를 리턴하기만 함 (출력 X)
add_print_to(print_hello)()
# 리턴된 wapper 함수는 호출된 부분 그대로 들어감
# 그래서 괄호를 써줘야 실행됨
'''
함수 시작
안녕하세요!
함수 끝
'''
def print_hello():
print('안녕하세요!')
def add_print_to(original):
def wrapper():
print('함수 시작')
original()
print('함수 끝')
return wrapper
print_hello = add_print_to(print_hello) # wrapper 가 print_hello로 들어감
print_hello() # wrapper()가 되니까 wrapper()가 실행됨
decorator 함수 사용법 :
@classmethod (데코레이터) def function(): 함수 내용 |
def add_print_to(original):
def wrapper():
print('함수 시작')
original()
print('함수 끝')
return wrapper
@add_print_to # print_hello 함수를 add_print_to로 꾸며주라는 뜻
def print_hello():
print('안녕하세요!')
print_hello()
'''
함수 시작
안녕하세요!
함수 끝
'''
클래스 메소드
class User:
count = 0
def __init__ (self, name, email, password):
self.name = name
self.email = email
self.password = password
User.count += 1
def say_hello(self):
print("안녕하세요! 저는 {}입니다!".format(self.name))
def __str__(self):
return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.nmae, self.email)
@classmethod
def number_of_users(cls):
print("총 유저수는: {}입니다.".format(cls.count))
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
user3 = User("Taeho", "taeho@codeit.kr", "123abc")
user4 = User("Lisa", "lisa@codeit.kr", "abc123")
# 클래스로 클래스메소드 호출
User.number_of_users() # 총 유저수는: 4입니다.
# 인스턴스로 클래스메소드 호출
user1.number_of_users() # 총 유저수는: 4입니다.
첫번째 파라미터로 클래스가 자동 전달됨.
클래스를 cls라는 파라미터로 전달 받음.
→ 첫 번째 파라미터의 이름은 꼭 cls로 쓰기
cls.count는 User.count와 같음
클래스메소드 number_of_users를 인스턴스 메소드로 작성해도 됨.
class User:
count = 0
def __init__ (self, name, email, password):
self.name = name
self.email = email
self.password = password
User.count += 1
def say_hello(self):
print("안녕하세요! 저는 {}입니다!".format(self.name))
def __str__(self):
return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.nmae, self.email)
# @classmethod
# def number_of_users(cls):
# print("총 유저수는: {}입니다.".format(cls.count))
def number_of_users(self):
print("총 유저 수는: {}입니다.".format(User.count))
user1 = User("Young", "young@codeit.kr", "123456")
user2 = User("Yoonsoo", "yoonsoo@codeit.kr", "abcdef")
user3 = User("Taeho", "taeho@codeit.kr", "123abc")
user4 = User("Lisa", "lisa@codeit.kr", "abc123")
User.number_of_users(user1) # 총 유저수는: 4입니다.
user1.number_of_users() # 총 유저수는: 4입니다.
처음에 number_of_users를 인스턴스 메소드가 아니라 클래스 메소드로 만든 것일까?
→ number_of_users가 인스턴스 변수를 사용하지 않기 때문임
(number_of_users는 self를 파마리터로 사용하지 않음)
인스턴스 메소드 vs 클래스 메소드
인스턴스 메소드 | 클래스 메소드 |
User.say_hello(user1) | User.number_of_users() |
user1.say_hello() ----> 인스턴스 자신이 첫 번째 파라미터로 자동 전달 |
user1.number_of_users() ----> 첫 번째 파라미터로 클래스 자동 전달 |
• 클래스 변수와 인스턴스 변수를 둘 다 쓰는 경우
- 인스턴스 메소드는 인스턴스 변수, 클래스 변수 모두 사용 가능함.
- 클래스 메소드는 인스턴스 변수 사용 불가능함.
→ 인스턴스 메소드를 사용
• 인스턴스 없이도 필요한 정보가 있는 경우
→ 클래스 메소드를 사용
ex. User.count는 인스턴스가 하나도 없더라도 '0개'라고 출력해야하니까 필요한 정보임
class User:
count = 0
def __init__ (self, name, email, password):
self.name = name
self.email = email
self.password = password
User.count += 1
def say_hello(self):
print("안녕하세요! 저는 {}입니다!".format(self.name))
def __str__(self):
return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.name, self.email)
@classmethod
def number_of_users(cls):
print("총 유저수는: {}입니다.".format(cls.count))
User.number_of_users() # 총 유저수는: 0입니다.
# 인스턴스가 하나도 없을 때에도 사용해야하면 "클래스 메소드" 사용
@classmethod # 잘못된 예시
def from_string(cls, string_params):
params_list = string_params.split(",")
cls.name = params_list[0]
cls.email = params_list[1]
cls.password = params_list[2]
return User(cls.name, cls.email, cls.password)
@classmethod # 바른 예시
def from_list(cls, list_params):
name = list_params[0]
email = list_params[1]
password = list_params[2]
return cls(name, email, password)
# 여기서 cls랑 User랑 똑같음
'''
메서드 내에서는 name, email, password를 사용하여 지역 변수로 처리
인스턴스를 생성할 때는 cls(name, email, password)과 같이 클래스 생성자를 사용하여 인스턴스를 생성
인스턴스 변수만 해당 값을 가지게 되며, 클래스 변수는 모든 인스턴스가 공유하지 않음.
'''
정적 메소드(static method)
인스턴스 변수, 클래스 변수를 전혀 다루지 않는 메소드
전달되는 파라미터가 없음.
@staticmethod
def is_valid_email(email_address):
return "@" in email_address
인스턴스, 클래스 두 가지 모두를 통해 사용 가능
print(User.is_valid_email("nadaegi"))
print(User.is_valid_email("nadaegi@codeit.kr"))
print(user1.is_valid_email("nadaegi"))
print(user1.is_valid_email("nadaegi@codeit.kr"))
어떠한 속성을 다루지 않음(인스턴스와 클래스 변수 사용X).
기능(행동)적인 역할만 하는 메소드를 정의할 때 사용함.
3. 미리 알고 가야 할 것들
파이썬은 순수 객체 지향 언어임.
파이썬 안에 있는 모든 것이 객체라는 뜻.
ex. '1'을 입력하면 int class로 만든 1을 나타내는 인스턴스가 생성됨.
가변 타입 객체 | 불변 타입 객체 |
한번 생성한 인스턴스의 속성 변경 가능 | 한번 생성한 인스턴스의 속성 변경 불가 |
ex. list, dict, 직접 작성한 클래스 | ex. bool, int, float, str, tuple |
→ 어떤 타입이냐에 따라 같은 상황에서도 다른 결과
mutable_object = [1, 2, 3]
immutable_object = (1, 2, 3)
# 리스트 인스턴스는 생성되고 나서도 그 속성을 바꿀 수 있음
mutable_object[0] = 4
print(mutable_object)
# 튜플 인스턴스는 생성된 후 그 속성을 바꿀 수 있음
immutable_object[0] = 4
print(immutable_object)
# 불변 타입 클래스의 인스턴스는 변수가 가리키는 객체 자체를 바꿀 수 있음
tuple_x = (6, 4)
tuple_x[0] = 4
tuple_x[1] = 1
print(tuple_x) # 생성된 객체의 속성을 바꾸는 것은 ERROR
# 새로운 인스턴스를 생성 후 해당 변수가 가리키게 하면 됨.
tuple_x = (6, 4)
tuple_x = (3, 1)
tuple_x = (2, 1, 3)
print(tuple_x) # (2, 1, 3)
절차지향 프로그래밍 vs 객체 지향 프로그래밍
절차 지향 프로그래밍 | 객체 지향 프로그래밍 |
프로그램을 만들 때 데이터와 함수를 합칠 수 없다. | 프로그램을 만들 때 데이터와 함수를 합칠 수 있다. |
프로그램을 명령어들을 순서대로 실행하는 것으로 본다. | 프로그램을 객체들이 순서대로 소통하는 과정으로 본다. |
ternary expression
Boolean 값에 따라 다른 값을 리턴하는 구문
condition = True
if condition:
condition_string = "nice"
else:
condition_string = "not nice"
condition = True
condition_string = "nice" if condition else "not nice"
def get_attacked(self, damage):
if self.is_alive(): # is_alive의 값이 true이면
if self.power > self.hp:
self.hp = 0
else:
self.hp -= damage # 다른 캐릭터의 power
def get_attacked(self, damage):
if self.is_alive(): # is_alive의 값이 true이면
self.hp = 0 if self.power > self.hp else self.hp - damage
list comprehension
squares = [x**2 for x in range(10)]
print(squares) # 출력: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
words = ["apple", "banana", "cherry", "date"]
lengths = [len(word) for word in words]
print(lengths) # 출력: [5, 6, 6, 4]
zfill
문자열을 최소 몇 자리 이상을 가진 문자열로 변환
모자란 부분은 왼쪽에 “0”을 채워줌
설정된 자릿수보다 더 긴 문자열이면 그 문자열을 그대로 출력함.
num_str = "42"
padded_num_str = num_str.zfill(6)
print(padded_num_str) # 출력: "000042"
large_num_str = "123456789"
padded_large_num_str = large_num_str.zfill(5)
print(padded_large_num_str) # 출력: "123456789" (길이가 이미 충분하므로 변화 없음)
rjust, ljust
문자열을 주어진 너비로 정렬함.
rjust = 문자열 오른쪽에 붙이고 해당문자를 왼쪽에 넣음.
ljust = 문자열을 왼쪽에 붙이고 해당 문자를 오른쪽에 넣음.
test1 = "12345".rjust(10, "k")
print(test1)
# 출력
# kkkkk12345
test2 = "12345".ljust(10, "k")
print(test2)
# 출력
# 12345kkkkk
from 모듈의 이름 import 불러올 변수/함수/클래스 이름
# math 모듈에서 sqrt 함수만 불러오기
from math import sqrt
# sqrt 함수 사용 예시
result = sqrt(25)
print(result) # 출력: 5.0
'코드잇 Codeit > Python / ML / DL' 카테고리의 다른 글
[코드잇] Python 환경 - 파이썬 모듈과 패키지 (1) | 2023.11.04 |
---|---|
[코드잇] 객체 지향 프로그래밍 in Python - 객체 지향 프로그래밍의 4개의 기둥 (0) | 2023.09.14 |
[코드잇] 데이터 사이언스 기초 - DataFrame 다루기 (0) | 2023.09.04 |
[코드잇] 데이터 사이언스 기초 - 데이터 사이언스 시작하기 (1) | 2023.09.02 |
[코드잇] 파이썬 프로그래밍 기초 - 파이썬 응용하기 (0) | 2023.08.04 |