소개
이 랩에서는 Python 의 클래스 데코레이터에 대해 배우고 Python 디스크립터 (descriptor) 를 복습하고 확장합니다. 이러한 개념들을 결합하여 강력하고 깔끔한 코드 구조를 만들 수 있습니다.
이 랩에서는 이전 디스크립터 개념을 기반으로 클래스 데코레이터를 사용하여 확장합니다. 이 조합을 통해 향상된 유효성 검사 기능을 갖춘 더 깔끔하고 유지보수하기 쉬운 코드를 만들 수 있습니다. 수정할 파일은 validate.py와 structure.py입니다.
디스크립터를 사용한 타입 검사 구현
이 단계에서는 타입 검사를 위해 디스크립터를 사용하는 Stock 클래스를 생성합니다. 하지만 먼저 디스크립터가 무엇인지 이해해 봅시다. 디스크립터는 Python 의 매우 강력한 기능입니다. 클래스에서 속성에 접근하는 방식을 제어할 수 있게 해줍니다.
디스크립터는 다른 객체에서 속성에 접근하는 방식을 정의하는 객체입니다. 이는 __get__, __set__, __delete__와 같은 특별한 메서드를 구현함으로써 이루어집니다. 이러한 메서드를 통해 디스크립터는 속성을 검색, 설정 및 삭제하는 방식을 관리할 수 있습니다. 디스크립터는 유효성 검사, 타입 검사 및 계산된 속성 (computed properties) 을 구현하는 데 매우 유용합니다. 예를 들어, 디스크립터를 사용하여 속성이 항상 양수이거나 특정 형식의 문자열인지 확인할 수 있습니다.
validate.py 파일에는 이미 검증자 클래스들 (String, PositiveInteger, PositiveFloat) 이 있습니다. 이러한 클래스를 사용하여 Stock 클래스의 속성을 검증할 수 있습니다.
이제 디스크립터를 사용하여 Stock 클래스를 만들어 보겠습니다.
먼저 편집기에서
stock.py파일을 엽니다.파일이 열리면 플레이스홀더 내용을 다음 코드로 바꿉니다.
## stock.py
from structure import Structure
from validate import String, PositiveInteger, PositiveFloat
class Stock(Structure):
_fields = ('name', 'shares', 'price')
name = String()
shares = PositiveInteger()
price = PositiveFloat()
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares):
self.shares -= nshares
## _fields 를 기반으로 __init__ 메서드 생성
Stock.create_init()
이 코드가 무엇을 하는지 자세히 살펴보겠습니다. _fields 튜플은 Stock 클래스의 속성을 정의합니다. 이것들은 Stock 객체가 가질 속성의 이름입니다.
name, shares, price 속성은 디스크립터 객체로 정의됩니다. String() 디스크립터는 name 속성이 문자열인지 확인합니다. PositiveInteger() 디스크립터는 shares 속성이 양의 정수인지 확인합니다. 그리고 PositiveFloat() 디스크립터는 price 속성이 양의 부동소수점 숫자인지 보장합니다.
cost 속성은 계산된 속성입니다. 주식 수와 주당 가격을 기반으로 주식의 총 비용을 계산합니다.
sell 메서드는 주식 수를 줄이는 데 사용됩니다. 판매할 주식 수를 인자로 이 메서드를 호출하면 해당 숫자를 shares 속성에서 차감합니다.
Stock.create_init() 줄은 클래스에 대한 __init__ 메서드를 동적으로 생성합니다. 이 메서드를 통해 name, shares, price 속성에 대한 값을 전달하여 Stock 객체를 생성할 수 있습니다.
코드를 추가한 후 파일을 저장합니다. 이렇게 하면 변경 사항이 저장되어 테스트를 실행할 때 사용할 수 있습니다.
이제 테스트를 실행하여 구현을 확인해 봅시다. 먼저 다음 명령을 실행하여 디렉토리를
~/project디렉토리로 변경합니다.
cd ~/project
그런 다음 다음 명령을 사용하여 테스트를 실행합니다.
python3 teststock.py
구현이 올바르다면 다음과 유사한 출력이 표시됩니다.
.........
----------------------------------------------------------------------
Ran 9 tests in 0.001s
OK
이 출력은 모든 테스트가 통과했음을 의미합니다. 디스크립터가 각 속성의 타입을 성공적으로 검증하고 있습니다!
Python 인터프리터에서 Stock 객체를 생성해 봅시다. 먼저 ~/project 디렉토리에 있는지 확인합니다. 그런 다음 다음 명령을 실행합니다.
cd ~/project
python3 -c "from stock import Stock; s = Stock('GOOG', 100, 490.1); print(s); print(f'Cost: {s.cost}')"
다음과 같은 출력이 표시되어야 합니다.
Stock('GOOG', 100, 490.1)
Cost: 49010.0
타입 검사를 위한 디스크립터를 성공적으로 구현했습니다! 이제 이 코드를 더 개선해 봅시다.
유효성 검사를 위한 클래스 데코레이터 생성
이전 단계에서는 구현이 작동했지만 중복이 있었습니다. _fields 튜플과 디스크립터 속성을 모두 지정해야 했습니다. 이는 매우 효율적이지 않으며 개선할 수 있습니다. Python 에서 클래스 데코레이터는 이 프로세스를 단순화하는 데 도움이 되는 강력한 도구입니다. 클래스 데코레이터는 클래스를 인수로 받아 일부 방식으로 수정한 다음 수정된 클래스를 반환하는 함수입니다. 클래스 데코레이터를 사용하면 디스크립터에서 필드 정보를 자동으로 추출하여 코드를 더 깔끔하고 유지보수하기 쉽게 만들 수 있습니다.
코드를 단순화하기 위해 클래스 데코레이터를 만들어 보겠습니다. 따라야 할 단계는 다음과 같습니다.
먼저 편집기에서
structure.py파일을 엽니다.다음으로,
structure.py파일의 맨 위, 모든 import 문 바로 뒤에 다음 코드를 추가합니다. 이 코드는 클래스 데코레이터를 정의합니다.
from validate import Validator
def validate_attributes(cls):
"""
Validator 인스턴스를 추출하고 _fields 목록을 자동으로 빌드하는
클래스 데코레이터
"""
validators = []
for name, val in vars(cls).items():
if isinstance(val, Validator):
validators.append(val)
## 검증자 이름을 기반으로 _fields 설정
cls._fields = [val.name for val in validators]
## 초기화 메서드 생성
cls.create_init()
return cls
이 데코레이터가 하는 일을 자세히 살펴보겠습니다.
- 먼저
validators라는 빈 목록을 만듭니다. 그런 다음vars(cls).items()를 사용하여 클래스의 모든 속성을 반복합니다. 속성이Validator클래스의 인스턴스인 경우 해당 속성을validators목록에 추가합니다. - 그 후 클래스의
_fields속성을 설정합니다.validators목록에 있는 검증자로부터 이름 목록을 만들어cls._fields에 할당합니다. - 마지막으로 클래스의
create_init()메서드를 호출하여__init__메서드를 생성한 다음 수정된 클래스를 반환합니다.
코드를 추가한 후
structure.py파일을 저장합니다. 파일을 저장하면 변경 사항이 유지됩니다.이제 이 새 데코레이터를 사용하도록
stock.py파일을 수정해야 합니다. 편집기에서stock.py파일을 엽니다.stock.py파일을 업데이트하여validate_attributes데코레이터를 사용하도록 합니다. 기존 코드를 다음으로 바꿉니다.
## stock.py
from structure import Structure, validate_attributes
from validate import String, PositiveInteger, PositiveFloat
@validate_attributes
class Stock(Structure):
name = String()
shares = PositiveInteger()
price = PositiveFloat()
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares):
self.shares -= nshares
변경한 내용을 확인해 보세요.
Stock클래스 정의 바로 위에@validate_attributes데코레이터를 추가했습니다. 이렇게 하면 Python 에validate_attributes데코레이터를Stock클래스에 적용하도록 지시합니다.- 데코레이터가 자동으로 처리하므로 명시적인
_fields선언을 제거했습니다. - 데코레이터가
__init__메서드 생성을 처리하므로Stock.create_init()호출도 제거했습니다.
결과적으로 클래스가 더 간단하고 깔끔해졌습니다. 데코레이터가 이전에 수동으로 처리했던 모든 세부 정보를 처리합니다.
- 이러한 변경을 한 후 모든 것이 예상대로 작동하는지 확인해야 합니다. 다음 명령을 사용하여 테스트를 다시 실행합니다.
cd ~/project
python3 teststock.py
모든 것이 올바르게 작동하면 다음과 같은 출력이 표시됩니다.
.........
----------------------------------------------------------------------
Ran 9 tests in 0.001s
OK
이 출력은 모든 테스트가 성공적으로 통과했음을 나타냅니다.
Stock 클래스를 대화형으로 테스트해 봅시다. 터미널에서 다음 명령을 실행합니다.
cd ~/project
python3 -c "from stock import Stock; s = Stock('GOOG', 100, 490.1); print(s); print(f'Cost: {s.cost}')"
다음과 같은 출력이 표시되어야 합니다.
Stock('GOOG', 100, 490.1)
Cost: 49010.0
훌륭합니다! 필드 선언 및 초기화를 자동으로 처리하여 코드를 단순화하는 클래스 데코레이터를 성공적으로 구현했습니다. 이렇게 하면 코드가 더 효율적이고 유지보수하기 쉬워집니다.
상속을 통한 데코레이터 적용
2 단계에서는 코드를 단순화하는 클래스 데코레이터를 만들었습니다. 클래스 데코레이터는 클래스를 인수로 받아 수정된 클래스를 반환하는 특별한 유형의 함수입니다. 클래스의 원본 코드를 수정하지 않고 클래스에 기능을 추가하는 데 유용한 Python 도구입니다. 하지만 각 클래스에 @validate_attributes 데코레이터를 명시적으로 적용해야 합니다. 이는 유효성 검사가 필요한 새 클래스를 만들 때마다 이 데코레이터를 추가해야 함을 의미하며, 이는 다소 번거로울 수 있습니다.
상속을 통해 데코레이터를 자동으로 적용하여 이를 더욱 개선할 수 있습니다. 상속은 하위 클래스가 부모 클래스의 속성과 메서드를 상속할 수 있는 객체 지향 프로그래밍의 기본 개념입니다. Python 3.6 에 도입된 __init_subclass__ 메서드를 사용하면 부모 클래스가 하위 클래스의 초기화를 사용자 정의할 수 있습니다. 이는 하위 클래스가 생성될 때 부모 클래스가 해당 클래스에 대한 일부 작업을 수행할 수 있음을 의미합니다. 이 기능을 사용하여 Structure를 상속하는 모든 클래스에 데코레이터를 자동으로 적용할 수 있습니다.
이를 구현해 보겠습니다.
편집기에서
structure.py파일을 엽니다. 이 파일에는Structure클래스의 정의가 포함되어 있으며,__init_subclass__메서드를 사용하도록 수정할 것입니다.Structure클래스에__init_subclass__메서드를 추가합니다.
class Structure:
_fields = ()
_types = ()
def __init__(self, *args):
if len(args) != len(self._fields):
raise TypeError(f'Expected {len(self._fields)} arguments')
for name, val in zip(self._fields, args):
setattr(self, name, val)
def __repr__(self):
values = ', '.join(repr(getattr(self, name)) for name in self._fields)
return f'{type(self).__name__}({values})'
@classmethod
def create_init(cls):
'''
_fields 로부터 __init__ 메서드 생성
'''
body = 'def __init__(self, %s):\n' % ', '.join(cls._fields)
for name in cls._fields:
body += f' self.{name} = {name}\n'
## 함수 생성 코드 실행
namespace = {}
exec(body, namespace)
setattr(cls, '__init__', namespace['__init__'])
@classmethod
def __init_subclass__(cls):
validate_attributes(cls)
__init_subclass__ 메서드는 클래스 메서드이므로 클래스 인스턴스가 아닌 클래스 자체에서 호출할 수 있습니다. Structure의 하위 클래스가 생성되면 이 메서드가 자동으로 호출됩니다. 이 메서드 내에서 하위 클래스 cls에 validate_attributes 데코레이터를 호출합니다. 이렇게 하면 Structure의 모든 하위 클래스에 자동으로 유효성 검사 동작이 적용됩니다.
- 파일을 저장합니다.
structure.py 파일에 변경 사항을 적용한 후에는 변경 사항이 적용되도록 저장해야 합니다.
이제 이 새로운 기능을 활용하도록
stock.py파일을 업데이트해 보겠습니다. 편집기에서stock.py파일을 열어 수정합니다. 이 파일에는Stock클래스의 정의가 포함되어 있으며, 자동 데코레이터 적용을 사용하기 위해Structure클래스를 상속하도록 수정할 것입니다.stock.py파일을 수정하여 명시적 데코레이터를 제거합니다.
## stock.py
from structure import Structure
from validate import String, PositiveInteger, PositiveFloat
class Stock(Structure):
name = String()
shares = PositiveInteger()
price = PositiveFloat()
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares):
self.shares -= nshares
다음과 같이 변경했습니다.
- 데코레이터가 상속을 통해 자동으로 적용되므로 더 이상 명시적으로 import 할 필요가 없으므로
validate_attributesimport 를 제거했습니다. Structure클래스의__init_subclass__메서드가 이를 적용하므로@validate_attributes데코레이터를 제거했습니다.- 이제 코드는 유효성 검사 동작을 얻기 위해
Structure로부터의 상속에만 의존합니다.
- 모든 것이 여전히 작동하는지 확인하기 위해 테스트를 다시 실행합니다.
cd ~/project
python3 teststock.py
테스트를 실행하는 것은 변경 사항으로 인해 문제가 발생하지 않았는지 확인하는 데 중요합니다. 모든 테스트가 통과하면 상속을 통한 자동 데코레이터 적용이 올바르게 작동하고 있음을 의미합니다.
모든 테스트가 통과하는 것을 볼 수 있습니다.
.........
----------------------------------------------------------------------
Ran 9 tests in 0.001s
OK
Stock 클래스를 다시 테스트하여 예상대로 작동하는지 확인해 보겠습니다.
cd ~/project
python3 -c "from stock import Stock; s = Stock('GOOG', 100, 490.1); print(s); print(f'Cost: {s.cost}')"
이 명령은 Stock 클래스의 인스턴스를 생성하고 해당 표현과 비용을 출력합니다. 출력이 예상대로라면 Stock 클래스가 자동 데코레이터 적용으로 올바르게 작동하고 있음을 의미합니다.
출력:
Stock('GOOG', 100, 490.1)
Cost: 49010.0
이 구현은 훨씬 더 깔끔합니다! __init_subclass__를 사용함으로써 데코레이터를 명시적으로 적용할 필요가 없어졌습니다. Structure를 상속하는 모든 클래스는 자동으로 유효성 검사 동작을 얻습니다.
행 변환 기능 추가
프로그래밍에서는 특히 CSV 파일과 같은 소스의 데이터를 다룰 때 데이터 행에서 클래스 인스턴스를 만드는 것이 유용한 경우가 많습니다. 이 섹션에서는 Structure 클래스의 인스턴스를 데이터 행에서 만들 수 있는 기능을 추가합니다. Structure 클래스에 from_row 클래스 메서드를 구현하여 이를 수행할 것입니다.
먼저 편집기에서
structure.py파일을 엽니다. 이곳에서 코드 변경을 수행할 것입니다.다음으로
validate_attributes함수를 수정합니다. 이 함수는Validator인스턴스를 추출하고_fields및_types목록을 자동으로 빌드하는 클래스 데코레이터입니다. 유형 정보도 수집하도록 업데이트할 것입니다.
def validate_attributes(cls):
"""
Validator 인스턴스를 추출하고 _fields 및 _types 목록을 자동으로 빌드하는
클래스 데코레이터
"""
validators = []
for name, val in vars(cls).items():
if isinstance(val, Validator):
validators.append(val)
## 검증자 이름을 기반으로 _fields 설정
cls._fields = [val.name for val in validators]
## 검증자 expected_types 를 기반으로 _types 설정
cls._types = [getattr(val, 'expected_type', lambda x: x) for val in validators]
## 초기화 메서드 생성
cls.create_init()
return cls
이 업데이트된 함수에서는 각 검증자로부터 expected_type 속성을 수집하여 _types 클래스 변수에 저장합니다. 이는 나중에 행에서 올바른 유형으로 데이터를 변환할 때 유용할 것입니다.
- 이제
Structure클래스에from_row클래스 메서드를 추가합니다. 이 메서드를 사용하면 목록 또는 튜플일 수 있는 데이터 행에서 클래스의 인스턴스를 만들 수 있습니다.
@classmethod
def from_row(cls, row):
"""
데이터 행 (목록 또는 튜플) 에서 인스턴스 생성
"""
rowdata = [func(val) for func, val in zip(cls._types, row)]
return cls(*rowdata)
이 메서드는 다음과 같이 작동합니다.
- 목록 또는 튜플 형식일 수 있는 데이터 행을 가져옵니다.
_types목록의 해당 함수를 사용하여 행의 각 값을 예상 유형으로 변환합니다.- 그런 다음 변환된 값을 사용하여 클래스의 새 인스턴스를 만들고 반환합니다.
이러한 변경을 한 후
structure.py파일을 저장합니다. 이렇게 하면 코드 변경 사항이 보존됩니다.from_row메서드가 예상대로 작동하는지 확인하기 위해 테스트해 보겠습니다.Stock클래스를 사용하여 간단한 테스트를 만들 것입니다. 터미널에서 다음 명령을 실행합니다.
cd ~/project
python3 -c "from stock import Stock; s = Stock.from_row(['GOOG', '100', '490.1']); print(s); print(f'Cost: {s.cost}')"
다음과 유사한 출력이 표시되어야 합니다.
Stock('GOOG', 100, 490.1)
Cost: 49010.0
문자열 값 '100'과 '490.1'이 올바른 유형 (정수 및 부동 소수점) 으로 자동 변환되었음을 알 수 있습니다. 이는 from_row 메서드가 올바르게 작동하고 있음을 보여줍니다.
- 마지막으로
reader.py모듈을 사용하여 CSV 파일에서 데이터를 읽어 보겠습니다. 터미널에서 다음 명령을 실행합니다.
cd ~/project
python3 -c "from stock import Stock; import reader; portfolio = reader.read_csv_as_instances('portfolio.csv', Stock); print(portfolio); print(f'Total value: {sum(s.cost for s in portfolio)}')"
CSV 파일의 주식을 보여주는 출력이 표시되어야 합니다.
[Stock('GOOG', 100, 490.1), Stock('AAPL', 50, 545.75), Stock('MSFT', 200, 30.47)]
Total value: 82391.5
from_row 메서드를 사용하면 CSV 데이터를 Stock 클래스의 인스턴스로 쉽게 변환할 수 있습니다. read_csv_as_instances 함수와 결합하면 구조화된 데이터를 로드하고 작업하는 강력한 방법을 갖게 됩니다.
메서드 인수 유효성 검사 추가
Python 에서 데이터를 유효성 검사하는 것은 견고한 코드를 작성하는 데 중요한 부분입니다. 이 섹션에서는 메서드 인수를 자동으로 유효성 검사하여 유효성 검사를 한 단계 더 발전시킬 것입니다. validate.py 파일에는 이미 @validated 데코레이터가 포함되어 있습니다. Python 의 데코레이터는 다른 함수를 수정할 수 있는 특별한 함수입니다. 여기서 @validated 데코레이터는 함수 인수를 주석과 비교하여 확인할 수 있습니다. Python 의 주석은 함수 매개변수 및 반환 값에 메타데이터를 추가하는 방법입니다.
코드를 수정하여 주석이 있는 메서드에 이 데코레이터를 적용해 보겠습니다.
- 먼저
validated데코레이터가 어떻게 작동하는지 이해해야 합니다. 편집기에서validate.py파일을 열어 검토합니다.
validated 데코레이터는 함수 주석을 사용하여 인수를 유효성 검사합니다. 함수가 실행되도록 허용하기 전에 각 주석이 달린 매개변수에 대해 검증자 클래스의 인스턴스를 만들고 validate 메서드를 호출하여 인수를 확인합니다. 예를 들어, 인수에 PositiveInteger가 주석으로 달린 경우 데코레이터는 PositiveInteger 인스턴스를 만들고 전달된 값이 실제로 양의 정수인지 확인합니다. 유효성 검사에 실패하면 모든 오류를 수집하고 자세한 오류 메시지와 함께 TypeError를 발생시킵니다.
이제
structure.py의validate_attributes함수를 수정하여 주석이 있는 메서드를validated데코레이터로 래핑합니다. 이는 클래스의 주석이 있는 모든 메서드가 인수를 자동으로 유효성 검사함을 의미합니다. 편집기에서structure.py파일을 엽니다.validate_attributes함수를 업데이트합니다.
def validate_attributes(cls):
"""
클래스 데코레이터로 다음을 수행합니다.
1. Validator 인스턴스를 추출하고 _fields 및 _types 목록을 빌드합니다.
2. 주석이 있는 메서드에 @validated 데코레이터를 적용합니다.
"""
## validated 데코레이터 가져오기
from validate import validated
## 검증자 디스크립터 처리
validators = []
for name, val in vars(cls).items():
if isinstance(val, Validator):
validators.append(val)
## 검증자 이름을 기반으로 _fields 설정
cls._fields = [val.name for val in validators]
## 검증자 expected_types 를 기반으로 _types 설정
cls._types = [getattr(val, 'expected_type', lambda x: x) for val in validators]
## 주석이 있는 메서드에 @validated 데코레이터 적용
for name, val in vars(cls).items():
if callable(val) and hasattr(val, '__annotations__'):
setattr(cls, name, validated(val))
## 초기화 메서드 생성
cls.create_init()
return cls
이 업데이트된 함수는 이제 다음을 수행합니다.
이전과 같이 검증자 디스크립터를 처리합니다. 검증자 디스크립터는 클래스 속성에 대한 유효성 검사 규칙을 정의하는 데 사용됩니다.
클래스에서 주석이 있는 모든 메서드를 찾습니다. 주석은 메서드 매개변수에 추가되어 인수의 예상 유형을 지정합니다.
해당 메서드에
@validated데코레이터를 적용합니다. 이렇게 하면 이러한 메서드에 전달된 인수가 주석에 따라 유효성 검사됩니다.이러한 변경을 한 후 파일을 저장합니다. 파일을 저장하는 것은 수정 사항이 저장되고 나중에 사용할 수 있도록 하는 데 중요합니다.
이제
Stock클래스의sell메서드를 수정하여 주석을 포함해 보겠습니다. 주석은 인수의 예상 유형을 지정하는 데 도움이 되며, 이는@validated데코레이터에서 유효성 검사에 사용됩니다. 편집기에서stock.py파일을 엽니다.sell메서드를 수정하여 유형 주석을 포함합니다.
## stock.py
from structure import Structure
from validate import String, PositiveInteger, PositiveFloat
class Stock(Structure):
name = String()
shares = PositiveInteger()
price = PositiveFloat()
@property
def cost(self):
return self.shares * self.price
def sell(self, nshares: PositiveInteger):
self.shares -= nshares
중요한 변경 사항은 nshares 매개변수에 : PositiveInteger를 추가하는 것입니다. 이는 Python(및 @validated 데코레이터) 에 PositiveInteger 검증자를 사용하여 이 인수를 유효성 검사하도록 지시합니다. 따라서 sell 메서드를 호출할 때 nshares 인수는 양의 정수여야 합니다.
- 모든 것이 여전히 작동하는지 확인하기 위해 테스트를 다시 실행합니다. 테스트를 실행하는 것은 변경 사항으로 인해 기존 기능이 손상되지 않았는지 확인하는 좋은 방법입니다.
cd ~/project
python3 teststock.py
모든 테스트가 통과하는 것을 볼 수 있습니다.
.........
----------------------------------------------------------------------
Ran 9 tests in 0.001s
OK
- 새로운 인수 유효성 검사를 테스트해 보겠습니다. 유효한 인수와 유효하지 않은 인수로
sell메서드를 호출하여 유효성 검사가 예상대로 작동하는지 확인해 보겠습니다.
cd ~/project
python3 -c "
from stock import Stock
s = Stock('GOOG', 100, 490.1)
s.sell(25)
print(s)
try:
s.sell(-25)
except Exception as e:
print(f'Error: {e}')
"
다음과 유사한 출력이 표시되어야 합니다.
Stock('GOOG', 75, 490.1)
Error: Bad Arguments
nshares: nshares must be >= 0
이는 메서드 인수 유효성 검사가 작동하고 있음을 보여줍니다! sell(25)에 대한 첫 번째 호출은 25가 양의 정수이므로 성공합니다. 그러나 sell(-25)에 대한 두 번째 호출은 -25가 양의 정수가 아니므로 실패합니다.
이제 다음을 위한 완전한 시스템을 구현했습니다.
- 디스크립터를 사용하여 클래스 속성을 유효성 검사합니다. 디스크립터는 클래스 속성에 대한 유효성 검사 규칙을 정의하는 데 사용됩니다.
- 클래스 데코레이터를 사용하여 필드 정보를 자동으로 수집합니다. 클래스 데코레이터는 필드 정보 수집과 같이 클래스의 동작을 수정할 수 있습니다.
- 행 데이터를 인스턴스로 변환합니다. 이는 외부 소스의 데이터로 작업할 때 유용합니다.
- 주석을 사용하여 메서드 인수를 유효성 검사합니다. 주석은 유효성 검사를 위해 인수의 예상 유형을 지정하는 데 도움이 됩니다.
이는 Python 에서 디스크립터와 데코레이터를 결합하여 표현력이 풍부하고 자체 유효성 검사가 가능한 클래스를 만드는 힘을 보여줍니다.
요약
이 실습에서는 강력한 Python 기능을 결합하여 깔끔하고 자체 유효성 검사가 가능한 코드를 만드는 방법을 배웠습니다. 속성 유효성 검사를 위한 디스크립터 사용, 코드 생성 자동화를 위한 클래스 데코레이터 생성, 상속을 통한 데코레이터 자동 적용과 같은 핵심 개념을 익혔습니다.
이러한 기술은 강력하고 유지보수 가능한 Python 코드를 만드는 데 강력한 도구입니다. 이를 통해 유효성 검사 요구 사항을 명확하게 표현하고 코드베이스 전체에 걸쳐 이를 적용할 수 있습니다. 이제 자체 Python 프로젝트에 이러한 패턴을 적용하여 코드 품질을 향상시키고 상용구 코드를 줄일 수 있습니다.