我有一个命名元组类型的子类:
class User(namedtuple('User', ['first_name'])):
__slots__ = ()
def __new__(cls, *args, **kwargs):
result = super().__new__(cls, *args, **kwargs)
if not result.first_name:
raise InvalidUserError({InvalidUserError.EMPTY_FIRST_NAME})
return result
创建新用户按预期工作:
>>> try: User(first_name='')
... except Exception as e: print(type(e))
<class 'InvalidUserError'>
但是,当使用 _replace
时,不会调用 __new__
方法:
>>> User(first_name='foo')._replace(first_name='')
User(first_name='')
有没有办法保证namedtuple
不变量?我正在使用 Python 3.4。
Python 总体上依赖于约定和良好的文档,而不是强烈强制执行不变量。即使没有 _replace()
,您也可以绕过 User.__new__()
:
>>> class X(tuple): __slots__ = ()
>>> x = C(('',))
>>> x.__class__ = User
>>> x
User(first_name='')
所以不,您永远无法严格执行此操作。只需避免使用 _replace()
,或使用调用 User.__new__()
的版本覆盖它,或检查不同级别的不变量。
_replace()
的示例实现:
def _replace(self, **kwargs):
return type(self)(**dict(vars(self), **kwargs))
我是一名优秀的程序员,十分优秀!