-
TIL. 31 클래스의 속성, 비공개 속성 사용하기TIL 2020. 11. 8. 17:45728x90
## 클래스 속성 사용하기
## 클래스에서 속성 만들기
## 속성(attribute)를 만들때는 "__init__ 메서드" 를 사용하며, 안에서 self.속성에 값을 할당하면 된다.
# class 클래스이름:
# def __init__(self):
# self.속성 = 값
class Person: def __init__(self): ## 속성을 정의한다는 뜻 self.hello = '안녕하세요.' def greeting(self): print(self.hello) james = Person() james.greeting() :: 안녕하세요.
## __init__ 메서드
## __init__ 메서드는 james = Person()처럼 클래스에 ( )(괄호)를 붙여서 인스턴스를 만들 때
호출되는 특별한 메서드이다 (클래스로 인스턴스를 만들때 호출되는 메서드)
## __init__(initialize)이라는 이름 그대로 인스턴스(객체)를 초기화한다.
class Person: def __init__(self): self.hello = '안녕하세요.'
## 이처럼 앞, 뒤로 __(밑줄 두개)가 붙은 메서드는 파이썬이 자동으로 호출해주는 메서드로
## 스페셜 메서드 (special method) 또는 매직 메서드 (magic method)라 부른다.
## 앞으로 파이썬의 여러 가지 기능을 사용할때는 이러한 스페셜 메서드를 채우는 식으로 사용하게 된다.
## 위 식에서의 인스턴스 및 메서드 호출
james = Person() james.greeting() # 안녕하세요.
## 지금까지 __init__로 속성을 만들고 greeting 메서드에서 속성을 사용하였다.
### 속성은 "__init__ 메서드"에서 만든다는 점 // self에 .(점)을 붙인 뒤 값을 할당한다는 점이 중요
## 클래스 안에서 속성을 사용할 때도 self.hello 처럼 self에 점을 붙여서 사용해야 한다.
## self의 의미
## self는 인스턴스 자기 자신을 의미합니다.
# 인스턴스가 생성될 때 self.hello = '안녕하세요.'처럼 자기 자신에 속성을 추가했다
# 여기서 __init__의 매개변수 self에 들어가는 값은 Person()이라 할 수 있다.
# 그리고 self가 완성된 뒤 james에 할당되고
# 이후 메서드를 호출하면 현재 인스턴스가 자동으로 매개변수 self에 들어온다. 그래서 greeting 메서드에서 print(self.hello)처럼 속성을 출력할 수 있는 것이다.
## 인스턴스를 만들때 값 받기
## 클래스로 인스턴스를 만들때의 값을 받는 방법
# class 클래스이름:
# def __init__(self, 매개변수1, 매개변수2):
# self.속성1 = 매개변수1
# self.속성2 = 매개변수2
class Person: def __init__(self, name, age, address): self.hello = '안녕' self.name = name self.age = age self.address = address ## name, age, address (매개변수 )를 그대로 self에 넣어 속성으로 만들었다. def greeting(self): print('{0} 저는 {1} 입니다.'.format(self.hello, self.name)) ## 속성에 접근하기 위해 self. 꼭 사용 maria = Person('마리아', 20, '서울시 서초구 반포동') maria.greeting() :: 안녕 저는 마리아 입니다. print('이름:', maria.name) # 마리아 print('나이:', maria.age) # 20 print('주소:', maria.address) # 서울시 서초구 반포동
## __init__메서드를 보면 self 다음 매개변수 3개를 지정하였다.
## 여기서 maria라는 인스턴스를 생성하면서 이름, 나이, 주소 등을 클래스의 ()안에 변수로 할당해준다.
## 이렇게 하면 이름은 '마리아', 나이는 20, 주소는 '서울시 서초구 반포동'인 maria 인스턴스가 만들어진다.
## 아래 greeting에 인수로 넣어주는 것은 greeting 메서드 안에서 __init__ 속성 값을 불러와 출력하는 형태이므로
## __init__ 메서드의 name, age, address 값이 입력된 상태가 아니게되어 error 가 발생한다.
## 매개변수가 들어있는 메서드에 인수를 넣어주는것에 맞다.
### 클래스 안에서 속성에 접근할때는 self.속성 형식을 이용한다.
def greeting(self): print('{0} 저는 {1} 입니다.'.format(self.hello, self.name))
### 클래스 바깥에서 속성에 접글할때는 인스턴스.속성 형식
print('이름:', maria.name) # 마리아 print('나이:', maria.age) # 20 print('주소:', maria.address) # 서울시 서초구 반포동
## 위처럼 인스턴스를 통해 접근하는 속성을 "인스턴스 속성"이라 부른다.
## 클래스에서의 위치 인수와 키워드 인수
## 클래스로 인스턴스를 만들 경우 위치, 키워드 인수를 사용할 수 있으며, 규칙은 함수와 같다.
## 위치인수
## 위치인수에서 리스트 언패킹을 사용하려면 *args를 사용,
이때 매개변수에서 값을 가져오려면 args[0]과 같이 인덱스로 접근해야 한다.
class Person: def __init__(self, *args): self.name = args[0] self.age = args[1] self.address = args[2] maria = Person(*['마리아', 20, '서울시 서초구 반포동'])
## 키워드 인수
## 키워드 인수와 딕셔너리 언패킹을 사용하려면 **kwargs를 사용,
이때 매개변수에서 값을 가져오려면 kwargs['name']과 같이 "키"값을 이용해 접근해야 한다.
class Person: def __init__(self, **kwargs): # 키워드 인수 self.name = kwargs['name'] self.age = kwargs['age'] self.address = kwargs['address'] maria1 = Person(name='마리아', age=20, address='서울시 서초구 반포동') maria2 = Person(**{'name': '마리아', 'age': 20, 'address': '서울시 서초구 반포동'})
### 인스턴스 생성 한 뒤에 속성 추가하기 및 특정 속성만 허용하기
## 지금까지는 클래스의 인스턴스 속성은 __init__ 메서드에서 추가한 뒤 사용했지만,
클래스를 먼저 만든 뒤에도 속성을 계속 추가할 수 있다.
# 인스턴스.속성 = 값
## 빈 클래스를 이용해 속성 추가하기
class Person: pass maria = Person() # 인스턴스 생성 maria.name = '마리아' # 인스턴스를 만든 뒤 속성 추가 print(maria.name) :: '마리아'
james = Person() # james 인스턴스 생성 james.name # maria 인스턴스에만 name 속성을 추가했으므로 james 인스턴스에는 name 속성이 없음 Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> james.name AttributeError: 'Person' object has no attribute 'name'
## 이렇게 추가한 속성은 해당 인스턴스(여기서는 maria)에만 생성이 된다.
## 클래스로 다른 인스턴스를 만들 경우 추가한 name 이라는 속성은 다른 인스턴스에 생성되지 않는다.
## 인스턴스 생성 후, __init__메서드가 아닌 다른 메서드로 속성 생성하기
class Person: def greeting(self): self.hello = '안녕하세요' # greeting 메서드에서 hello 속성 추가 maria = Person() maria.hello # 아직 hello 속성이 없음 Traceback (most recent call last): File "<pyshell#22>", line 1, in <module> maria.hello AttributeError: 'Person' object has no attribute 'hello' maria.greeting() # greeting 메서드를 호출해야 maria.hello # hello 속성이 생성됨 :: '안녕하세요'
## 특정 속성만 허용하고 다른 속성은 제한하는 방법
## 인스턴스는 자유롭게 속성을 추가 할 수 있지만 특정 속성만 허용하고 다른 속성은 제한을 둘 수 있다.
## 이떄 클래스에서 __slots__에 허용할 속성 이름을 리스트로 넣어주면 되며, 반드시 속성이름은 문자열 이여야만 한다.
# __slots__ = ['속성이름1, '속성이름2']
class Person: __slots__ = ['name', 'age'] # name, age만 허용(다른 속성은 생성 제한) maria = Person() maria.name = '마리아' # 허용된 속성 maria.age = 20 # 허용된 속성 maria.address = '서울시 서초구 반포동' # 허용되지 않은 속성은 추가할 때 에러가 발생함 Traceback (most recent call last): File "<pyshell#32>", line 1, in <module> maria.address = '서울시 서초구 반포동' AttributeError: 'Person' object has no attribute 'address'
## 앞서 만든 Person 클래스에서 hello, name, age, address 속성이 있었다.
## 이 속성들은 메서드에서 self로 접근 할 수 있고,
인스턴스.속성 형식으로 클래스 바깥에서 접근 할 수 있었다.
class Person: def __init__(self, name, age, address): self.hello = '안녕하세요.' self.name = name self.age = age self.address = address maria = Person('마리아', 20, '서울시 서초구 반포동') maria.name :: '마리아'
## 비공개 속성 사용하기
## 클래스 바깥에서는 접근 할 수 없고, 클래스 안에서만 사용할 수 있는 비공개 속성(private attribute)
## __속성 (밑줄 두개) // __속성__ 밑줄이 양옆으로 올 경우 비공개 속성이 아님
# class 클래스이름:
# def __init__(self, 매개변수)
# self.__속성 = 값
class Person: def __init__(self, name, age, address, wallet): self.name = name self.age = age self.address = address self.__wallet = wallet # 변수 앞에 __를 붙혀 비공개 속성으로 만듬 maria = Person('마리아', 20, '서울시 서초구 반포동', 10000) maria.__wallet -= 10000 # 클래스 바깥에서 비공개 속성에 접근하였으므로 error Traceback (most recent call last): File "C:\project\class_private_attribute_error.py", line 9, in <module> maria.__wallet -= 10000 # 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함 AttributeError: 'Person' object has no attribute '__wallet'
## 비공개 속성은 클래스 안의 메서드에서만 접근이 가능하다.
## 아래와 같이 pay 메서드를 이용해 돈을 내고 남은 금액이 얼마인지 알아보는 함수를 작성해보자
class Person: def __init__(self, name, age, address, wallet): self.name = name self.age = age self.address = address self.__wallet = wallet # 변수 앞에 __를 붙여서 비공개 속성으로 만듦 def pay(self, amount): self.__wallet -= amount print('이제 돈이 {} 남았네요.'.format(self.__wallet)) maria = Person('마리아', 20, '서울시 서초구 반포동', 10000) maria.pay(3000) :: 이제 돈이 7000 남았네요.
## 지불해야하는 금액에 따라 지갑 안의 돈보다 많으면 결제를 진행하고 부족하면 잔액 부족을 출력한다.
def pay (self, amount): if amount > self.__wallet: print('잔액부족') # 잔액 출력하지 않고 return 만 사용하기도 함 return self.__wallet -= amount print(self.__wallet) maria = Person('마리아', 20, '서울시 서초구 반포동', 10000) maria.pay(5000) :: 5000
### 이처럼 비공개 속성은 클래스 바깥으로 드러내고 싶지 않은 값에 사용한다.
### 즉, 중요한 값인데 바깥에서 함부로 바꾸면 안될 때 비공개 속성을 주로 사용한다.
### 따라서 비공개 속성을 바꾸는 경우는 클래스 안의 메서드로 한정한다.
### 지금까지 클래스 사용 방법에 대해 알아보았다.
### 클래스는 특정 개념을 표현(정의)만 할 뿐 사용을 하려면 인스턴스로 만들어야 한다는 점이 중요
### 그리고 속성, 메서드를 사용할 때는 self와 인스턴스를 통해 사용해야 한다는 점도 기억하자
## 공개 속성과 비공개 속성
## 공개 속성(public attribute) == 클래스 바깥에서 접근할 수 있는 속성
## 비공개 속성(private attribute) == 클래스 바깥에서 접근할 수 없는 속성
## 비공개 메서드
## 속선 뿐 아닌 메서드에서도 __(밑줄 두개)로 시작하는 비공개 매서드를 만들 수 있다.
class Person: def __greeting(self): print('Hello') def hello(self): self.__greeting() # 클래스 안에서는 비공개 메서드를 호출할 수 있음 james = Person() james.__greeting() # 에러: 클래스 바깥에서는 비공개 메서드를 호출할 수 없음
## 보통 내부에서만 호출되어야 하는 메서드를 비공개 메서드로 만드는데
## 예로 게임 케릭터가 마나를 소비하여 스킬을 사용한다고 가정하자
## 마나 소비량을 계산해서 차감하는 메서드는 비공개로 만들고, 스킬을 쓰는 메서드는 공개 메서드로 만들면 된다.
## 만약 마나를 차감하는 메서드가 공개로 되어있으면,
마음대로 마나를 차감 시 킬 수 있으므로 잘못된 클래스 설계가 된다.
728x90'TIL' 카테고리의 다른 글
TIL.33 클래스 상속(기반 클래스 및 파생클래스) (0) 2020.11.10 TIL.32 클래스의 속성과 메서드 (0) 2020.11.09 TIL.30 클래스와 메서드 사용하기 (0) 2020.11.07 TIL. 29 전역 변수, 지역변수, 클로저 알아보기 (0) 2020.11.06 TIL. 28 람다 표현식(lambda) 사용하기 (0) 2020.11.05