2

我有一个命名元组类型的这个子类:

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。

4

1 回答 1

2

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))
于 2014-09-09T10:34:47.743 回答