class Citizen:
def __init__(self, age_value):
self._age = age_value
@property
def age(self):
print("나이를 리턴합니다.")
return self._age
@age.setter
def age(self, age_value):
print("나이를 새로 설정합니다.")
self._age = age_value
citizen = Citizen(20)
print(citizen.age)
위 코드에서 마지막 줄에 있는 citizen.age 이 부분이 실행될 때 age 변수의 값을 읽는 것이 아니라 바로 아래의 age 메소드가 실행된다. age 메소드 위에 붙은 @property 데코레이터 때문이다.
코드의 실행결과는 아래와 같다.
나이를 리턴합니다.
20
그렇다면 아래와 같이 한줄을 더 추가하여 코드를 실행해보자.
class Citizen:
def __init__(self, age_value):
self._age = age_value
@property
def age(self):
print("나이를 리턴합니다.")
return self._age
@age.setter
def age(self, age_value):
print("나이를 새로 설정합니다.")
self._age = age_value
citizen = Citizen(20)
citizen.age = 30
print(citizen.age)
citizen.age = 30 이 코드를 추가하였고 실행 결과는 아래와 같다.
나이를 새로 설정합니다.
나이를 리턴합니다.
30
결과는 나이를 30으로 바꾸고 출력했다. 그런데 맨 위에 나이를 새로 설정합니다 라는 문자열이 출력됐다. 이것은 지금 age 메소드에 있는 문자열이다. 결국 citizen.age = 30 이 실행될 때 바로 이 함수가 실행됐다는 의미이다. 이것 또한 프로퍼티 때문이다.
1. @property 가 붙은 age 메소드(A)가 있으면 Citizen 클래스의 인스턴스.age, 이 코드가 실행될 때 A가 실행되고,
2. @age.setter가 붙은 age 메소드(B)가 있으면 Citizen 클래스의 인스턴스.age = 어떤 숫자값 이 코드가 실행될 때 B가 실행된다는 뜻이다.
중요한 것은 실제로 나이를 나타내는 인스턴스 변수는 언더바 하나가 붙은 _age가 아니라 age라는 것이다. 그러니까 마치 age 변수의 값을 읽고 쓰는 것처럼 써있더라고 실제 age 변수가 아니라는 것이다.
이런 기능이 왜 필요한 것일까?
프로퍼티가 있으면 코드를 수정할 일이 생겼을 때 최소한의 노력으로 코드를 수정할 수 있다.
예를 들어 Citizen 클래스 프로퍼티 기능이 없고, 인스턴스 변수 name이 있다고 해보자.
class Citizen:
def __init__(self, name, age_value):
self.name = name
self.age = age_value
# ...
c1 = Citizen("Tom", 20)
c2 = Citizen("Mike", 10)
c3 = Citizen("Sally", 23)
#...
print(c1.name, c1.age)
print(c2.name, c2.age)
print(c3.name, c3.age)
#...
Citizen 클래스의 인스턴스를 여러 개 생성하고 그 들의 나이를 모두 출력하는 코드이다.
하지만, 나이뿐만 아니라 나이를 보고 성인인지 여부도 출력해야 한다고 해보자.
일단 Citizen 클래스에 성인 나이의 기준을 나타내기 위한 클래스 변수 age_threshold 를 새로 추가한다.
class Citizen:
age_threshold = 19
def __init__(self, name, age_value):
self.age = age_value
성인여부를 출력하려면 아래와 같이 바꿔야한다.
# ...
c1 = Citizen("Tom", 20)
c2 = Citizen("Mike", 10)
c3 = Citizen("Sally", 23)
#...
if c1.age >= Citizen.age_threshold :
print(True, c1.name, c1.age)
else :
print(False, c1.name, c1.age)
if c2.age >= Citizen.age_threshold :
print(True, c2.name, c2.age)
else :
print(False, c2.name, c2.age)
if c3.age >= Citizen.age_threshold :
print(True, c3.name, c3.age)
else :
print(False, c3.name, c3.age)
#...
하지만 @property를 사용하면 아래와 같이 간단하게 바꿀 수 있다.
class Citizen:
age_threshold = 19
def __init__(self, name, age_value):
self.name = name
self._age = age_value
@property
def age(self):
if (self._age >= Citizen.age_threshold):
print(True)
else:
print(False)
return self._age
# ...
c1 = Citizen("Tom", 20)
c2 = Citizen("Mike", 10)
c3 = Citizen("Sally", 23)
# ...
print(c1.name, c1.age)
print(c2.name, c2.age)
print(c3.name, c3.age)
# ...
이렇게 파이썬에서 프로퍼티 기능을 사용하면 객체의 속성을 다루는 코드를 수정하지 않고도 변경사항을 손쉽게 반영할 수 있다. 어떤 객체의 속성 값을 읽고, 속성 값을 설정하는 코드는 자주 쓰게 된다.
프로퍼티가 없다면 속성에 관해서 매번 변경사항이 있을 때마다 그런 코드들을 썼던 부분을 모두 수정해줘야한다. 하지만 프로퍼티를 사용하면 그런 부분을 두고 프로퍼티만 추가해서 변경사항을 빠르게 반영할 수 있다. 이것이 프로퍼티의 강력한 기능이다.
'Python' 카테고리의 다른 글
[Python] 추상 클래스 사용하기 (@abstractmethod) (0) | 2022.04.07 |
---|---|
[Python] 데코레이터 사용하기 (0) | 2022.04.07 |
[Python] 프로퍼티 (Property) 사용하기 (1/2) (0) | 2022.04.07 |
[Python] numpy 패키지를 이용하여 FFT 하기 (1) | 2021.07.28 |
[Windows] 에서 파이썬 설치하기 (0) | 2021.01.16 |
댓글