-
TIL.32 클래스의 속성과 메서드TIL 2020. 11. 9. 17:50728x90
## 속성에는 클래스 속성과 인스턴스 속성으로 나눈다.
## 이전까지 배웠던 속성은 인스턴스 속성이었다.
## 클래스 속성
## 클래스 속성은 클래스 아래에 바로 속성을 만들면 된다.
# class 클래스이름:
# 속성 = 값
# 가방에 물건을 넣는 동작으로 알아보자.
class Person: bag = [] # 클래스 속성 bag def put_bag(self, stuff): self.bag.append(stuff) james = Person() james.put_bag('책') maria = Person() maria.put_bag('열쇠') print(james.bag) # ['책', '열쇠'] print(maria.bag) # ['책', '열쇠']
## 예상되는 결과로는 "책" // "열쇠" 처럼 따로따로 결과가 나와야하는데
물건이 합쳐져서 출력이 되는 것을 볼 수 있다.
## 즉, 클래스 속성은 클래스에 속해 있으며 "모든 인스턴스"에서 공유한다.
class Person: bag = [] def put_bag(self, stuff): self.bag.append(stuff) ## self 사용하여 클래스 속성 bag 접근
## put_bag 메서드에서 클래스 속성에 접근하기 위해 self를 사용하였다.
## 사실 self는 현재 인스턴스를 뜻하므로 클래스 속성을 지정할때 사용하기에는 에매한 부분이 있다.
### 따라서, 클래스 속성에 접글할때는 클래스 이름으로 접근하면 코드가 더 명확해진다.
# 클래스.속성
class Person: bag = [] def put_bag(self, stuff): Person.bag.append(stuff) # 클래스 이름으로 클래스 속성에 접근 print(Person.bag)
## print 함수를 사용한 것과 같이 클래스 바깥에서도 클래스.속성으로 접근할 수 있다.
## 속성, 메서드 이름을 찾는 순서
## 파이썬에서는 속성, 메서드 이름을 찾을때 인스턴스 < 클래스 순으로 찾아간다.
## 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 되므로 james.bag, maria.bag도 문제 없이 동작한다.
## 겉보기에는 인스턴스 속성을 사용하는 것 같지만 실제로는 클래스 속성이다.
# 인스턴스와 클래스에서 __dict__ 속성을 출력해보면
현재 인스턴스와 클래스의 속성을 딕셔너리로 확인할 수 있습니다.
# 인스턴스.__dict__
# 클래스.__dict__
## james.bad 을 사용했을때의 클래스 속성을 찾는 과정
## 인스턴스 속성 사용하기
## 위 물건을 가방에 넣는 동작에서 여러 사람이 가방을 공유하지 않으려면 인스턴스 속성을 사용하면 된다.
## 그냥 bag을 인스턴스 속성으로 만들어주자
class Person: def __init__(self): self.bag = [] def put_bag(self, stuff): self.bag.append(stuff) james = Person() james.put_bag('책') maria = Person() maria.put_bag('열쇠') print(james.bag) # 책 print(maria.bag) # 열쇠
### 즉, 인스턴스 속성은 인스턴스 별로 독립되어 서로 영향을 주지 않음을 알 수 있다.
### 클래스 속성과 인스턴스 속성의 차이점
## 클래스 속성: 모든 인스턴스가 공유. 인스턴스 전체가 사용해야 하는 값을 저장할 때 사용
## 인스턴스 속성: 인스턴스별로 독립되어 있음. 각 인스턴스가 값을 따로 저장해야 할 때 사용
## 비공개 클래스 속성 사용하기
## 클래스 속성도 __(밑줄 두개)로 비공개 클래스 속성을 만들 수 있으며,
클래스 안에서만 접근이 가능하며 클래스 바깥에서는 접근이 불가능하다.
# class 클래스이름:
# __속성 = 값 # 비공개 클래스 속성
## 게임 케릭터는 아이템을 최대 10개 까지 보유 할 수 있다는 코드로 알아보자.
class Knight: __item_limit = 10 # 비공개 클래스 속성 def print_item_limit(self): print(Knight.__item_limit) # 클래스 안에서만 접근할 수 있음 x = Knight() x.print_item_limit() # 10 print(Knight.__item_limit) # 클래스 바깥에서는 접근할 수 없음 // error
## 아이템이 최대 10개 보유 제한인데 클래스를 사용하는 사람이 마음대로 1000으로 수정하면 곤란하기 때문에,
비공개 클래스 속성으로 사용한 것이다.
## 클래스와 메서드의 독스트링 사용하기
## 함수와 마찬가지로 클래스와 메서드에서도 독스트링을 사용할 수 있다.
## :(콜론) 바로 다음 줄에 """ """(큰따옴표 세 개) 또는 ''' '''(작은따옴표 세 개)로 문자열을 입력
## 클래스의 독스트링 -> 클래스.__doc__
## 메서드의 독스트링 -> 클래스.메서드.__doc__ 또는 인스턴스.메서드__doc__ 형식을 사용한다.
class Person: '''사람 클래스입니다.''' def greeting(self): '''인사 메서드입니다.''' print('Hello') print(Person.__doc__) # 사람 클래스입니다. print(Person.greeting.__doc__) # 인사 메서드입니다. maria = Person() print(maria.greeting.__doc__) # 인사 메서드입니다.
## 정적 메서드 사용하기
## 지금까지는 클래스의 메서드를 호출할때 인스턴스를 생성하고 이를 통해 호출하였다.
## 이번에는 인스턴스를 사용하지 않고 클래스에서 바로 호출 할 수 있는 정적 메서드와 클레스 메서드를 알아보자.
## 정적 메서드
## 클래스에서 바로 호출 할 수 있는 메서드를 정적 메서드라 한다.
## @staticmethod 를 붙히는 것으로 정적 메서드를 생성할 수 있으며, 이때 매개변수에 self를 지정하지 않는다.
# class 클래스이름:
# @staticmethod
# def 메서드(매개변수1, 매개변수2):
# 코드
## @staticmethod 처럼 @가 붙은 것을 "데코레이터"라고 하며 메서드(함수)에 추가 기능을 구현 할 때 사용한다.
class Calc: @staticmethod def add (a, b): print(a + b) def mul (a, b): print(a * b)
## Calc 클래스에서 @staticmethod를 붙혀서 add 메서드와 mul 메서드를 만들었다.
## 정적 메서드를 호출할때는 아래와 같이 클래스에서 메서드를 바로 호출하면 된다.
# 클래스.메서드()
Calc.add(10, 20) # 30 Calc.mul(20, 30) # 600
## 정적 메서드에서는 self를 받지 않으므로 인스턴스 속성에는 접근 할 수 없다.
## 그래서 보통 정적 메서드는 인스턴스 속성, 인스턴스 메서드가 필요 없을때 사용한다.
## 만든 Calc 클래스에 들어있는 add, mul 메서드는 숫자 두개를 받아서 더하거나 곱할 뿐
인스턴스의 속성은 필요하지 않다.
## 정적 메서드 사용하는 이유
## 정적 메서드는 실행이 외부 상태에 영향을 끼치지 않는 순수 함수 (pure function)을 만들 때 사용한다.
## 즉, 정적 메서드는 인스턴스의 상태를 변화시키지 않는 메서드를 만들때 사용한다.
## 파이썬 자료형의 인스턴스 메서드와 정적 메서드
## 파이썬의 자료형도 인스턴스 메서드와 정적 메서드로 나누어져 있다.
## 아래의 예로 세트에 요소를 더할때는 인스턴스 메서드를 사용하고,
합집합을 구할때는 정적 메서드를 사용하도록 만들어져 있다.
a = {1, 2, 3, 4} a.update({5}) # 인스턴스 메서드 a # {1, 2, 3, 4, 5} set.union({1, 2, 3, 4}, {5}) # 정적(클래스) 메서드 # {1, 2, 3, 4, 5}
## 이처럼 내용을 변경해야할 때 --> 인스턴스 메서드
## 인스턴스 내용과 상관없이 결과만 구현하면 될때 --> 정적 메서드를 사용하면 된다.
## 클래스 메서드 사용하기
## 정적 메서드와 비슷하지만, 차이점이 있는 클래스 메서드
## 클래스 메서드는 @classmethod를 붙이면 된다. 여기서, 첫번째 매개변수는 반드시 cls (class) 로 지정해야한다.
# class 클래스이름:
# @classmethod
# def 메서드(cls, 매개변수1, 매개변수2):
# 코드
class Person: count = 0 # 클래스 속성 def __init__(self): Person.count += 1 # 인스턴스를 만들때 클래스 속성 count에 1을 누적시킴 / ## self.count도 가능하지만 클래스 속성에 사용할때는 클래스명.속성으로 접근하자 # 코드가 더 명확해진다. @classmethod def pi_count(cls): print('{}명 생성되었습니다.'.format(cls.count)) james = Person() maria = Person() james.pi_count() # 2명 생성되었습니다. (클래스 속성은 "모든 인스턴스에 공유한다") maria.pi_count() # 2명 생성되었습니다. (클래스 속성은 "모든 인스턴스에 공유한다") Person.pi_count() # 2명 생성되었습니다.
## 먼저, 인스턴스가 만들어질때마다 호출되는 __init__메서드를 이용해
인스턴스가 만들어질때마다 count에 1을 더하는 코드를 만들어준다.(누적)
## 클래스 속성에 접근하기 위해 self.속성 보다는 클래스.속성을 사용하는 것으로 하자.
@classmethod def pi_count(cls): print('{}명 생성되었습니다.'.format(cls.count))
## @classmethod를 붙혀 클래스 메서드를 만들어 준다.
## 클래스 메서드는 첫 번째 매개변수는 cls이며, 여기에는 현재 클래스(Person)이 들어온다.
## 따라서 cls.count 처럼 "cls로 클래스 속성 count에 접근 할 수 있다."
Person.pi_count() # 2명 생성되었습니다.
## pi_count는 클래스 메서드이므로 클래스.메서드() 형식 처럼 클래스로 호출해준다.
### 클래스 메서드와 정적 메서드의 공통점과 차이점
## 공통점 == 인스턴스 없이 호출 할 수 있다는 점
## 차이점 == 클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용함
## 특히 cls를 사용하면 메서드 안에서 현재 클래스의 인스턴스를 만들 수 있다는 점
## 즉, cls == 클래스 이므로 cls() == Person() 과 같다
@classmethod def create(cls): p = cls() # cls()로 인스턴스 생성 return p
728x90'TIL' 카테고리의 다른 글
TIL.34 클래스 상속(오버라이딩 및 추상클래스) (0) 2020.11.11 TIL.33 클래스 상속(기반 클래스 및 파생클래스) (0) 2020.11.10 TIL. 31 클래스의 속성, 비공개 속성 사용하기 (0) 2020.11.08 TIL.30 클래스와 메서드 사용하기 (0) 2020.11.07 TIL. 29 전역 변수, 지역변수, 클로저 알아보기 (0) 2020.11.06