클래스 인스턴스의 속성을 검증하는 올바른 접근 방식
다음과 같은 간단한 Python 클래스가 있습니다.
class Spam(object):
__init__(self, description, value):
self.description = description
self.value = value
다음 제약 조건을 확인하고 싶습니다.
- "설명은 비워 둘 수 없습니다."
- "값은 0보다 커야합니다."
1. 스팸 개체를 만들기 전에 데이터의 유효성을 검사 해야합니까 ?
2. __init__
방법 에 대한 데이터를 확인 ?
3. is_valid
Spam 클래스에 메서드를 만들고 spam.isValid ()로 호출합니까?
4. is_valid
Spam 클래스에 정적 메서드를 만들고 Spam.isValid (description, value)?
5. setters 선언에 대한 데이터를 확인합니까?
6. 등
잘 디자인 된 / 파이 토닉 / 장황하지 않은 (많은 속성이있는 수업에서) / 우아한 접근 방식을 추천 해 주시겠습니까?
Python 속성 을 사용 하여 각 필드에 개별적으로 규칙을 명확하게 적용하고 클라이언트 코드가 필드를 변경하려고 할 때에도 적용 할 수 있습니다.
class Spam(object):
def __init__(self, description, value):
self.description = description
self.value = value
@property
def description(self):
return self._description
@description.setter
def description(self, d):
if not d: raise Exception("description cannot be empty")
self._description = d
@property
def value(self):
return self._value
@value.setter
def value(self, v):
if not (v > 0): raise Exception("value must be greater than zero")
self._value = v
__init__
함수 내에서도 규칙을 위반하려는 모든 시도에서 예외가 발생하며이 경우 객체 생성이 실패합니다.
업데이트 : 2010 년과 지금 사이에 operator.attrgetter
다음 사항에 대해 배웠습니다 .
import operator
class Spam(object):
def __init__(self, description, value):
self.description = description
self.value = value
description = property(operator.attrgetter('_description'))
@description.setter
def description(self, d):
if not d: raise Exception("description cannot be empty")
self._description = d
value = property(operator.attrgetter('_value'))
@value.setter
def value(self, v):
if not (v > 0): raise Exception("value must be greater than zero")
self._value = v
개체가 생성 될 때만 값의 유효성을 검사하고 잘못된 값을 전달하는 것이 프로그래밍 오류로 간주되면 어설 션을 사용합니다.
class Spam(object):
def __init__(self, description, value):
assert description != ""
assert value > 0
self.description = description
self.value = value
이것은 당신이 얻는 것만 큼 간결하며 이것이 객체를 만들기위한 전제 조건임을 명확하게 문서화합니다.
Unless you're hellbent on rolling your own, you can simply use formencode. It really shines with many attributes and schemas (just subclass schemas) and has a lot of useful validators builtin. As you can see this is the "validate data before creating spam object" approach.
from formencode import Schema, validators
class SpamSchema(Schema):
description = validators.String(not_empty=True)
value = validators.Int(min=0)
class Spam(object):
def __init__(self, description, value):
self.description = description
self.value = value
## how you actually validate depends on your application
def validate_input( cls, schema, **input):
data = schema.to_python(input) # validate `input` dict with the schema
return cls(**data) # it validated here, else there was an exception
# returns a Spam object
validate_input( Spam, SpamSchema, description='this works', value=5)
# raises an exception with all the invalid fields
validate_input( Spam, SpamSchema, description='', value=-1)
You could do the checks during __init__
too (and make them completely transparent with descriptors|decorators|metaclass), but I'm not a big fan of that. I like a clean barrier between user input and internal objects.
if you want to only validate those values passed to the constructor, you could do:
class Spam(object):
def __init__(self, description, value):
if not description or value <=0:
raise ValueError
self.description = description
self.value = value
This will of course will not prevent anyone from doing something like this:
>>> s = Spam('s', 5)
>>> s.value = 0
>>> s.value
0
So, correct approach depends on what you're trying to accomplish.
'Programing' 카테고리의 다른 글
SQL Server 2005에서 전화 번호를 저장하려면 어떤 데이터 형식을 사용해야합니까? (0) | 2020.11.02 |
---|---|
Valgrind Massif 도구 출력 그래픽 인터페이스? (0) | 2020.11.02 |
Git 병합되지 않은 경로 문제 (0) | 2020.11.02 |
NullReferenceException에 null에 대한 정보가 포함되지 않는 이유는 무엇입니까? (0) | 2020.11.02 |
Chrome 자동 형식 input = number (0) | 2020.11.02 |