如何创建不可变对象的副本并更新某些属性?

时间:2019-04-10 13:22:36

标签: python python-3.x

我定义了一个不变的类,如here所述。现在,我想定义一个复制方法,该方法将给定实例的所有属性转移到新实例,并允许为任何现有属性提供新值。

这就是我所拥有的:

from operator import itemgetter

class Foo(tuple):
    __slots__ = []

    def __new__(cls, a, b, c):
        return tuple.__new__(cls, (a, b, c))

    a = property(itemgetter(0))
    b = property(itemgetter(1))
    c = property(itemgetter(2))

    def copy(self, a='', b='', c=''):
        return Foo(
            a=a if a else self.a,
            b=b if b else self.b,
            c=c if c else self.c,
        )

期望的行为:

instance_a = Foo('a', 'b', 'c')
instance_b = instance_a.copy(c='d')

assert instance_b.a == 'a'
assert instance_b.b == 'b'
assert instance_b.c == 'd'

问题: 除了if else构造(即a=a if a else self.a)之外,还有没有更优雅的方法可以在新属性和现有属性之间进行选择?

2 个答案:

答案 0 :(得分:2)

标准库中的

collections.namedtuple做同样的事情,并且也有一个方便的复制方法,称为_replace

from collections import namedtuple

Foo = namedtuple('Foo', ('a', 'b', 'c'))

x = Foo(1, 2, 3)
print(x)
y = x._replace(b='hello')
print(y)

输出

Foo(a=1, b=2, c=3)
Foo(a=1, b='hello', c=3)

答案 1 :(得分:1)

a or self.a
但是,如果将bool(a)评估为False,它将具有意外的行为。但这已经是您的问题了。