优雅的方式,有一个几乎复制构造函数,允许更新一些成员

时间:2018-05-16 16:25:26

标签: python python-3.x python-3.6

我有一个容器类的实例,它作为其他几个实例的基础。它在示例中称为data0。我希望能够制作副本,然后更新副本的一些成员。

是的,可以使用copy模块完成,创建副本并为成员分配新值。但是如果容器类是不可变的呢?

我希望能够实现将类转换为映射(keys__getitem__)并使__init__接受基类加上一些修改所需的内容。这可能是因为您可以更新字典的方式:

x = {'a': 0, 'b': 1, 'c': 2}
y = {'b': 7}
z = {**x, 'b': 7}
print(z)  # {'a': 0, 'b': 7, 'c': 2}

所以我希望能够做到的是:

data3 = Container(**data0, b=7)
print(data3)

这是我试过的:

class Container:
    KEYS = ('a', 'b', 'c')

    def __init__(self, a=None, b=None, c=None):
        self._a = a
        self._b = b
        self._c = c

    @property
    def a(self):
        return self._a
    @property
    def b(self):
        return self._b
    @property
    def c(self):
        return self._c

    def keys(self):
        return Container.KEYS

    def __getitem__(self, key):
        if key not in Container.KEYS:
            raise KeyError(key)
        return getattr(self, key)

    def __str__(self):
        return f'{self.__class__.__name__}(a={self.a}, b={self.b}, c={self.c})'

data0 = Container(a=1, b=2, c=3)
print(data0) # Container(a=1, b=2, c=3)
data1 = Container(**data0)  # 'copy constructor'
print(data1)  # Container(a=1, b=2, c=3)
data2 = Container(**{**data0, 'b':7})
print(data2)  # Container(a=1, b=7, c=3)

最后一种方法有效,但很难看......

如上所述:我希望能够做到的是:

data3 = Container(**data0, b=7)
print(data3)

但这(可以理解)失败并显示错误消息

  

TypeError:type object为关键字参数' b'

获取了多个值

我该如何解决这个问题?或者是否有更明显的方法从更新成员的给定基础创建新实例?

或者是标准的方法,只是从具有所需值作为默认值的类继承?

class Container1(Container):
    def __init__(self, a=1, b=2, c=3):
       super().__init__(a=a, b=b, c=c)

data3 = Container1(b=7)
print(data3)  # Container1(a=1, b=7, c=3)

这有点冗长,并且data3的类型为Container1 ......

我的尝试在python 3.5上的行为与在{3}}上的python 3.6不同。

0 个答案:

没有答案