@property, @setter, @deleter
1. 소개
- 클래스의 메서드를 속성(attribute) 처럼 다룰 수 있게 해주는 데코레이터
- 속성처럼
obj.name 처럼 호출하지만, 실제로는 내부 메서드가 실행되어 속성을 조회하는 방식
- 속성을 메서드로 다루기 때문에, 속성 조회, 검증, 계산 등의 통제를 자동으로 할 수 있게 해준다.
| 데코레이터 |
기능 |
@property |
getter 를 만드는 데코레이터로, 메서드를 읽기 전용 속성처럼 만들어준다. 속성을 읽을 때 사용. |
@setter |
메서드를 속성에 값을 대입하는 setter로 만들어준다. 값의 검증 로직을 추가할 수 있다. 속성을 대입할 때 사용. |
@deleter |
메서드를 통해 속성을 제거할 때 사용된다. |
2. 사용법
(1) @property
1
2
3
4
5
6
7
8
9
10
| class User:
def __init__(self, name:str):
self._name = name
@property
def name(self):
return self._name
u = User("소크라테스")
print(u.name)
|
(2) @setter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class User:
def __init__(self, name:str|None = None):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
u = User()
u.name = "소크라테스"
print(u.name)
|
(3) @deleter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class User:
def __init__(self, name:str):
self._name = name
@property
def name(self):
return self._name
@name.deleter
def name(self):
del self._name
u = User("소크라테스")
del u.name
print(u.name)
|
1
| AttributeError: 'User' object has no attribute '_name'
|
2. 사용하는 이유
(1) 속성값을 읽을 때 변환 로직을 넣기 위해
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@property
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
t = Temperature(30)
print("celsius : ", t.celsius)
print("fahrenheit : ", t.fahrenheit)
|
1
2
| celsius : 30
fahrenheit : 86.0
|
(2) 속성값을 넣을 때 값을 검증하기 위해
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| class User:
def __init__(self, email:str|None = None):
self._email = email
@property
def email(self):
return self._email
@email.setter
def email(self, value):
if "@" not in value:
raise ValueError("올바른 이메일 형식이 아닙니다.")
self._email = value
u = User()
u.email = "abcdefg"
|
(3) 외부에서의 사용 방식은 유지하고, 내부 구현을 바꿀 때
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Dollar:
def __init__(self, dollar):
self._dollar = dollar
@property
def korean_won(self):
exchange_rate = 1400
return self._dollar * exchange_rate
d = Dollar(1)
print(d.korean_won)
# >> 1400
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Dollar:
def __init__(self, dollar):
self._dollar = dollar
@property
def korean_won(self):
exchange_rate = 1500
return self._dollar * exchange_rate
d = Dollar(1)
print(d.korean_won)
# >> 1500
|
(4) 기능을 가지면서, 호출할 때에는 일반 속성처럼 호출
- 값의 변환 기능을 가지는 일반 메서드를 만들 경우
1
2
3
4
5
6
7
8
9
| class Temperature:
def __init__(self, celsius):
self._celsius = celsius
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
t = Temperature(30)
t.fahrenheit()
|
1
2
3
4
5
6
7
8
9
10
| class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def fahrenheit(self):
return self._celsius * 9 / 5 + 32
t = Temperature(30)
t.fahrenheit
|
3. 결론
@property 를 사용하는 것은, “이 값은 객체의 속성이다”라는 의미를 더 자연스럽게 표현함
- 이처럼 상태, 성질(속성)처럼 보이고 싶은 경우 property 데코레이터를 사용하고
- 행동 중심, 특정 작업처럼 보이고 싶은 경우엔 일반 메서드를 사용하면 된다.
Comments