элегантный способ иметь конструктор почти копирования, который позволяет обновлять некоторые элементы - PullRequest
0 голосов
/ 16 мая 2018

У меня есть экземпляр класса контейнера, который служит основой для нескольких других экземпляров.в примере это называется 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: объект типа получил несколько значений для ключевого аргумента '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 ведет себя иначе, чем на Python3,6 как описано / спросили здесь .

...