안녕하세요, 온라인 코딩 스쿨 코드잇입니다.
오늘은 지난 시간에 이어 파이썬의 프로퍼티를 계속 공부해보겠습니다.
지난 시간 강의(프로퍼티 1편)
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 데코레이터 때문이라는 것두요.
@property def age(self): print('나이를 리턴합니다.') return self._age
그래서 코드를 실행하면..
나이를 리턴합니다. 20
이렇게 age 메소드 안에 있었던 '나이를 리턴합니다.'라는 문자열이 출력됩니다!
이번 시간에는 코드를 한줄 더 추가해봅시다. 아까 코드에서 맨 아래 2줄 사이에 코드 한 줄을 추가할게요.
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 메소드에 있는 문자열입니다.
@age.setter def age(self, age_value): print('나이를 새로 설정합니다.') self._age = age_value
그럼 결국 citizen.age = 30 이 실행될 때 바로 이 함수가 실행됐다는 의미입니다. 이것도 지금 프로퍼티 때문입니다.
그러니까 지금 Citizen 클래스에서
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
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) #...
이런 식으로 바꿔줘야 합니다. 지금 그나마 시민 인스턴스가 3명이니까 다행이지 훨씬 많았다면 정말 힘들었을 겁니다. 하지만 프로퍼티를 사용하면 기존 코드를 건드리지 않아도 코드 수정이 가능합니다. Citizen 클래스를 이렇게 바꿔주면 되거든요.
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) #...
지금 프로퍼티가 붙은 age 메소드를 추가했고 원래의 인스턴스 변수 age 는 _age 로 이름을 변경했습니다. 이렇게 하면 코드 내용 중 c1.age, c2.age, c3.age 이 부분들이 각각 실행될 때 @propery 가 붙은 age 메소드가 실행될 겁니다. 그럼 나이를 리턴하기 전에 나이를 보고 미성년자 여부(True 또는 False)를 출력할 겁니다. 그러면 기존에 Citizen 클래스를 사용하던 코드를 하나도 수정하지 않고 변경사항을 반영할 수 있는 겁니다. 신기하죠?
이렇게 파이썬에서 프로퍼티 기능을 사용하면 객체의 속성을 다루는 코드를 수정하지 않고도 변경사항을 손쉽게 반영할 수 있습니다. 어떤 객체의 속성의 값을 읽고, 속성의 값을 설정하는 코드는 아주 자주 쓰게 되는 코드입니다.
프로퍼티가 없다면 속성에 관해서 매번 변경사항이 있을 때마다 그런 코드들을 썼던 부분을 모두 수정해줘야 합니다. 하지만 프로퍼티를 사용하면 그런 부분을 그대로 두고 프로퍼티만 추가해서 변경사항을 빠르게 반영할 수 있습니다. 이것이 프로퍼티의 강력한 기능입니다.
그런데 혹시 프로퍼티가 어떤 기능을 갖는지는 알겠는데 왜 그렇게 동작할까라고 궁금하신 분도 계신가요?
사실 프로퍼티의 작동 원리를 깊게 알려면 꽤 많은 것들을 공부해야 합니다. 하지만 어렵다고 그냥 넘어갈 수는 없겠죠?
다음 글부터 프로퍼티의 작동 원리를 이해하기 위해 알아야할 기초 개념부터 하나씩 알려드릴게요.