_replace不会调用命名元组子类的__new__

时间:2014-09-09 10:02:52

标签: python python-3.x namedtuple

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

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。

1 个答案:

答案 0 :(得分: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))