출처: https://www.pythontutorial.net/python-oop/python-properties/
Introduction to class properties
다음은 이름과 나이라는 두 가지 속성이 있는 Person 클래스를 정의하고 Person 클래스의 새 인스턴스를 만듭니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
john = Person('John', 18)
age는 Person 클래스의 인스턴스 속성이므로 다음과 같이 새 값을 할당할 수 있습니다.
john.age = 19
다음 할당도 기술적으로 유효합니다.
john.age = -1
그러나 나이는 의미상 올바르지 않습니다.
나이가 0 또는 음수가 아닌지 확인하려면 if 문을 사용하여 다음과 같이 검사를 추가합니다.
age = -1
if age <= 0:
raise ValueError('The age must be positive')
else:
john.age = age
그리고 age 속성에 값을 할당 할 때마다이 작업을 수행해야합니다 . 이것은 반복적이고 유지 관리가 어렵습니다.
이러한 반복을 방지하려면 getter 및 setter라는 한 쌍의 메서드를 정의할 수 있습니다.
Getter and setter
getter 및 setter 메서드는 인스턴스 속성에 액세스하기 위한 인터페이스를 제공합니다.
- getter는 속성의 값을 반환합니다.
- setter가 속성에 대한 새 값을 설정합니다.
이 예제에서는 age 속성을 비공개로 설정 하고(규칙에 따라) age 속성을 조작할 getter 및 setter를 정의할 수 있습니다 .
다음은 age property에 대해 getter 및 setter가 있는 새 Person 클래스를 보여 줍니다.
class Person:
def __init__(self, name, age):
self.name = name
self.set_age(age)
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
작동 방식.
Person 클래스 에서 set_age()는 setter이고 get_age()는 getter입니다. 규칙에 따라 게터와 세터의 이름은 get_<attribute>() 및 set_<attribute>()입니다.
set_age() 메서드에서 나이가 0보다 작거나 같으면 ValueError가 발생합니다. 그렇지 않으면 age 인수를 _age 속성에 할당 합니다.
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
get_age()메소드는 _age 속성의 값을 반환합니다.
def get_age(self):
return self._age
__init__() 메서드 에서 set_age() setter 메서드를 호출하여 _age 속성을 초기화합니다.
def __init__(self, name, age):
self.name = name
self.set_age(age)
다음은 age 속성에 잘못된 값을 할당하려고 시도합니다.
john = Person('John', 18)
john.set_age(-19)
그리고 파이썬은 예상대로 ValueError 를 발행했습니다 .
ValueError: The age must be positive
이 코드는 잘 작동합니다. 그러나 이전 버전과의 호환성 문제가 있습니다. ( age와 _age )
잠시 동안 Person 클래스를 릴리스했고 다른 개발자가 이미 사용하고 있다고 가정합니다. 이제 getter와 setter를 추가하면 Person을 사용하는 모든 코드가 더 이상 작동하지 않습니다.
이전 버전과의 호환성을 유지하면서 getter 및 setter 메서드를 정의하려면 property() 클래스를 사용할 수 있습니다.
The Python property class
property 클래스는 property 개체를 반환합니다. property() 클래스의 구문은 다음과 같습니다.
property(fget=None, fset=None, fdel=None, doc=None)
property()에는 다음과 같은 매개 변수가 있습니다.
- fget 은 속성의 값을 가져오는 함수, 또는 getter 메서드
- fset 은 속성의 값을 설정하는 함수, 또는 setter 메서드
- fdel 은 속성을 삭제하는 함수
- doc 는 docstring(주석)
다음은 property() 함수를 사용하여 Person 클래스의 age 속성을 정의합니다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
age = property(fget=get_age, fset=set_age)
Person 클래스에서는 property()를 호출하여 새 property 객체를 만들고 property 객체를 age 속성에 할당합니다.
age는 인스턴스 속성이 아니라 클래스 속성입니다.
다음은 Person.age가 property 개체임을 보여 줍니다.
print(Person.age)
Output:
<property object at 0x000001F5F5149180>
다음은 Person 클래스의 새 인스턴스를 만들고 age 속성에 액세스합니다.
john = Person('John', 18)
john.__dict__는 john 객체의 인스턴스 속성을 저장합니다. 다음은 john.__dict__의 내용을 보여줍니다 .
print(john.__dict__)
Output:
{'_age': 18, 'name': 'John'}
출력에서 명확하게 알 수 있듯이 john.__dict__에는 age 속성이 없습니다.( _age 존재 )
다음은 john 객체의 age 속성에 값을 할당합니다.
john.age = 19
이 경우 파이썬은 john.__dict__에서 age 속성을 먼저 찾습니다. 파이썬은 john.__dict__에서 age 속성을 찾지 못하기 때문에 Person.__dict__에서 age 속성을 찾습니다.
Person.__dict__는 Person 클래스의 클래스 속성을 저장합니다. 다음은 Person.__dict__의 내용을 보여줍니다.
pprint(Person.__dict__)
Output:
mappingproxy({'__dict__': <attribute '__dict__' of 'Person' objects>,
'__doc__': None,
'__init__': <function Person.__init__ at 0x000002242F5B2670>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Person' objects>,
'age': <property object at 0x000002242EE39180>,
'get_age': <function Person.get_age at 0x000002242F5B2790>,
'set_age': <function Person.set_age at 0x000002242F5B2700>})
파이썬은 Person.__dict__에서 age 속성을 찾기 때문에, age property 객체에 값을 할당할 때 age 개체를 호출합니다.
john.age = 19
파이썬은 fset 인수에 할당된 함수인 set_age()를 호출합니다.
마찬가지로, age property 객체에서 읽을 때 Python은 fget 인수에 할당된 함수인 get_age() 메서드를 실행합니다.
property()클래스를 사용하면 이전 버전과의 호환성을 유지하면서 클래스에 property를 추가 할 수 있습니다. 실제로는 속성을 먼저 정의합니다. 나중에 필요한 경우 클래스에 property를 추가할 수 있습니다.
전체 Code
from pprint import pprint
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def set_age(self, age):
if age <= 0:
raise ValueError('The age must be positive')
self._age = age
def get_age(self):
return self._age
age = property(fget=get_age, fset=set_age)
print(Person.age)
john = Person('John', 18)
pprint(john.__dict__)
john.age = 19
pprint(Person.__dict__)
Summary
- Python은 property() 클래스를 사용하여 클래스의 속성을 정의합니다.
- 실제로는 속성을 먼저 정의합니다. 나중에 필요한 경우 클래스에 property를 추가하여 클래스 속성을 구현한다.
'Python Object-oriented Programming' 카테고리의 다른 글
delete-property (0) | 2023.04.04 |
---|---|
readonly-property (0) | 2023.04.04 |
__del__ Method (0) | 2023.04.04 |
Dependency Inversion Principle (0) | 2023.04.04 |
__bool__ Method (0) | 2023.04.03 |
댓글