파이썬 클래스의 작성
•
인스턴스 메소드의 경우, 첫번째 파라미터는 self가 된다.
class User:
def say_hello(some_user):
print("안녕하세요! 저는 {}입니다".format(some_user.name))
def login(self,my_email,my_password):
if(self.email == my_email and self.password == my_password):
print("로그인 성공")
else:
print("로그인 실패")
user1 = User()
user2 = User()
user3 = User()
user1.name = "김대위"
user1.email = "captain@codeit.kr"
user1.password = "12345"
user1.login(user1,"captain@codeit.kr","12345")
user1.login("captain@codeit.kr","12345")
Python
복사
인스턴스의 함수를 정의할 때, 인스턴스가 넘어오는 첫번째 파라미터는 self를 쓰자
특수 메소드
어떤 상황에서 자동으로 호출 되는 것
class User:
def __init__(self,name,email,password):
self.name = name
self.email = email
self.password = password
user1 = User("Young", "young@codeit.kr", "123456")
print(user1.name, user1.email, user1.password)
Python
복사
클래스를 호출할 때 바로 __init __ 함수가 호출됨
class User:
def __init__(self,name,email,pw):
self.name = name
self.email = email
self.pw = pw
def __str__(self):
return "사용자: {}, 이메일: {} 비밀번호: **** ".format(self.name,self.email)
user1 = User("강영훈","younghoon@codeit.kr","123456")
user2 = User("이윤수","yoonsoo@codeit.kr","1q2w3e4r")
print(user1)
print(user2)
Python
복사
__str __ 함수, dunder str 메소드는 print를 했을 때 사용된다.
클래스 변수
각 인스턴스 별로 개별로 존재하는 게 아니라, 인스턴스 전체가 공유하는 변수가 필요할 때 클래스 변수를 사용한다.
class User:
count = 0
def __init__(self,name,email,pw):
self.name = name
self.email = email
self.pw = pw
User.count += 1
user1 = User("강영훈","younghoon@codeit.kr","123456")
user2 = User("이윤수","yoonsoo@codeit.kr","abcef")
user3 = User("서혜린","lisa@codeit.kr","123abc")
User.count = 5
print(User.count)
print(user1.count)
print(user2.count)
print(user3.count)
Python
복사
데코레이터
함수를 꾸며서 새로운 함수를 사용할 수 있다.
스프링에 AOP같은 기능이다.
어떤 함수에 대해서 동일한 기능을 반복적으로 묶어서 새롭게 정의하는 것
이건 흔히 쓰는 방법
def add_print_to(original):
def wrapper():
print("함수 시작")
original()
print("함수 끝")
return wrapper
@add_print_to
def print_hello():
print("안녕하세요!")
#add_print_to(print_hello)()
#print_hello = add_print_to(print_hello)
print_hello()
Python
복사
원리를 보면
def print_hello():
print("안녕하세요!")
def add_print_to(original):
def wrapper():
print("함수 시작")
original()
print("함수 끝")
return wrapper
print_hello = add_print_to(print_hello)
print_hello()
Python
복사
이런 식으로 c언어로 치면 함수 포인터를 받아서 함수 포인터를 돌려주는 것
클래스 메소드
클래스 메소드는 인스턴스 말고 전체 클래스에서 동일하게 적용되는 메소드를 위한 것
아래와 같이 작성한다.
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))
user1 = User("강영훈","younghoon@codeit.kr","123456")
user2 = User("이윤수","yoonsoo@codeit.kr","abcdef")
user3 = User("서혜린","lisa@codeit.kr","123abc")
User.number_of_users()
user1.number_of_users()
Python
복사
클래스 메소드 → 클래스 변수
인스턴스 메소드 → 인스턴스 변수
인스턴스 메소드는 인스턴스 변수와 클래스 변수 모두 접근 가능
클래스 메소드는 클래스 변수만 접근 가능, 인스턴스 변수에는 접근할 방법이 없다
인스턴스가 하나도 없을 때에도 사용하려면 클래스 메소드를 사용한다.
class User:
def __init__(self, name, email, password):
self.name = name
self.email = email
self.password = password
@classmethod
def from_string(cls, string_params):
parameter_list = string_params.split(",")
name = parameter_list[0]
email = parameter_list[1]
password = parameter_list[2]
return cls(name,email,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)
# 코드를 쓰세요
# 유저 생성 및 초기값 설정
younghoon = User.from_string("강영훈,younghoon@codeit.kr,123456")
yoonsoo = User.from_list(["이윤수", "yoonsoo@codeit.kr", "abcdef"])
print(younghoon.name, younghoon.email, younghoon.password)
print(yoonsoo.name, yoonsoo.email, yoonsoo.password)
Python
복사
서로 다른 형태의 input에 대해서 동일한 인스턴스를 만들어내야할 때 필요한 함수를 implementation하는 거
이거는 인스턴스 메소드로는 안 될거다.
정적 메소드
이때까지
•
인스턴스 메소드
•
클래스 메소드
를 배웠습니다. 메소드의 종류는 총 3가지라고 했죠? 아직 하나가 더 남았습니다.
바로 정적 메소드(static method)입니다. 정적 메소드는 인스턴스 변수, 클래스 변수를 전혀 다루지 않는 메소드입니다.
아래 코드를 볼까요?
class User:
count = 0
def __init__(self, name, email, pw):
self.name = name
self.email = email
self.pw = pw
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))
@staticmethod
def is_valid_email(email_address):
return "@" in email_address
Python
복사
지금 User 클래스에서 is_valid_email 메소드가 정적 메소드입니다. 정적 메소드는 메소드 정의 위에 @staticmethod 데코레이터를 표시해야 합니다. is_valid_email 메소드는 파라미터 email_address로 받은 문자열에 @가 들어있는지 체크합니다.
정적 메소드는
•
인스턴스 메소드의 self
•
클래스 메소드의 cls
같은 자동 전달되는 파라미터가 없습니다.
그리고 정적 메소드는 아래 코드처럼 인스턴스, 클래스 두 가지 모두를 통해 사용 가능합니다.
print(User.is_valid_email("taehosung"))
print(User.is_valid_email("taehosung@codeit.kr"))
print(user1.is_valid_email("taehosung"))
print(user1.is_valid_email("taehosung@codeit.kr"))
Plain Text
복사
False
True
False
True
Plain Text
복사
정적 메소드는 언제 사용할까요?
# 인스턴스 메소드def __str__(self):
return "사용자: {}, 이메일: {}, 비밀번호: ******".format(self.name, self.email)
# 클래스 메소드@classmethod
def number_of_users(cls):
print("총 유저 수는: {}입니다".format(cls.count))
# 정적 메소드@staticmethod
def is_valid_email(email_address):
return "@" in email_address
Python
복사
User 클래스에는 인스턴스 메소드, 클래스 메소드, 정적 메소드가 있습니다.
1.
인스턴스 메소드 __str__는 인스턴스 변수인 self.name, self.email을 사용하고,
2.
클래스 메소드 number_of_user는 클래스 변수인 cls.count를 사용합니다.
3.
하지만 is_valid_email 메소드에선 아무 변수도 사용하고 있지 않네요.
인스턴스 변수나 클래스 변수 중 아무것도 사용하지 않을 메소드라면 정적 메소드로 만들면 됩니다. 그러니까 어떤 속성을 다루지 않고, 단지 기능(행동)적인 역할만 하는 메소드를 정의할 때 정적 메소드로 정의하면 됩니다. 이제 여러분은 메소드의 종류에는
•
인스턴스 메소드
•
클래스 메소드
•
정적 메소드
이 3가지가 있다는 것을 기억해주세요.
미리 알고 가야할 내용
파이썬은 순수 객체 지향 언어
모든 것이 객체다!
기본적으로 int, list, string, tuple, dictionary, function 등은 다 클래스로 되어있고 그거에 대한 인스턴스를 만들어서 쓸 뿐이다.
가변 타입 vs 불변 타입
가변 → mutable
불가변 → immutable
한 번 생성한 인스턴스의 속성을 변경할 수 있으면 가변
안되면 불변
가변 → list, dict
불변 → bool, int, float, str,tuple
알면 좋은 함수들
앞으로 자주 마주치게 될 함수들을 미리 살펴봅시다.
max, min 함수
print(max(2, 5))# => 5
print(max(2, 7, 5))# => 7
print(min(2, 5))# => 2
print(min(2, 7, 5, 11, 6))# => 2
Plain Text
복사
max 함수는 파라미터 중 가장 큰 값을, min 함수는 파라미터 중 가장 작은 값을 리턴합니다. 두 함수 모두 원하는 개수만큼의 파라미터들을 넘겨줄 수 있습니다.
sum 함수
int_list = [1, 2, 3, 4, 5]
int_tuple = (4, 3, 6, 1, 2)
int_dict = {1: "one", 2: "two", 3: "three"}
print(sum(int_list))# => 15
print(sum(int_tuple))# => 16
print(sum(int_dict))# => 6
Plain Text
복사
sum 함수는 리스트, 튜플, 딕셔너리에 있는 숫자형 요소들의 합을 리턴합니다. sum 함수에 딕셔너리를 파라미터로 넘기면 key들의 합을 리턴합니다.
ternary expression
condition = True
if condition:
condition_string = "nice"
else:
condition_string = "not nice"
print(condition_string)# => nice
Plain Text
복사
condition = True
condition_string = "nice" if condition else "not nice"
print(condition_string)# => nice
Plain Text
복사
위의 코드와 아래의 코드는 같은 내용입니다. "nice" if condition else "not_nice" 이 구문은
1.
condition이 True 일 때는 "nice"가 되고
2.
False 일 때는 "not_nice"가 된다는 뜻입니다.
이렇게 불린(Boolean) 값에 따라 다른 값을 리턴하는 구문을 ternary expression이라고 합니다. ternary expression을 사용하면 if, else로 복잡하게 표현해야 하는 구문을 간단하게 나타낼 수 있습니다.
list comprehension
int_list = [1, 2, 3, 4, 5, 6]
squares = []
for x in int_list:
squares.append(x**2)
print(squares)# [1, 4, 9, 16, 25, 36]
Plain Text
복사
int_list = [1, 2, 3, 4, 5, 6]
squares = [x**2 for x in int_list]
print(squares)# [1, 4, 9, 16, 25, 36]
Plain Text
복사
위 코드와 아래 코드는 같은 뜻입니다. list comprehension은 새로운 리스트를 만드는 간편한 방법입니다. 특정 리스트나 튜플을 바탕으로 리스트를 생성할 때
1.
[] 안에 원하는 값을 리턴하는 식 (x**2) 뒤에
2.
for문을 써줍니다(for x in int_list).
이렇게 쓰면 int_list 의 각 요소들을 제곱해준 값들로 이루어진 새로운 리스트가 생성됩니다.
x**2 부분에 여러분이 원하는 식을 쓰면 되겠죠?
zfill 메소드
이 메소드는 문자열을 최소 몇 자리 이상을 가진 문자열로 변환시켜줍니다. 이때 만약 모자란 부분은 왼쪽에 “0”을 채워주는데요. 예를 들어 만약 "1".zfill(2)을 하면 "01"을 리턴합니다. 그리고 설정된 자릿수보다 이미 더 긴 문자열이라면 그 문자열을 그대로 출력합니다. 그러니까 "333".zfill(2) 와 같이 하면 문자열 그대로 “333”을 리턴합니다. 아래 코드를 보면 더 쉽게 이해할 수 있습니다. 이 메소드는 문자열을 예쁘고 통일감있게 출력하고자 할 때 자주 사용되니까 꼭 기억해주세요.
print("1".zfill(6))
print("333".zfill(2))
print("a".zfill(8))
print("ab".zfill(8))
print("abc".zfill(8))
Plain Text
복사
실행 결과
000001
333
0000000a
000000ab
00000abc
Plain Text
복사