Eu gostaria de criar uma cópia de um objeto. Eu quero que o novo objeto possua todas as propriedades do objeto antigo (valores dos campos). Mas eu quero ter objetos independentes. Portanto, se eu alterar os valores dos campos do novo objeto, o objeto antigo não deverá ser afetado por isso.
199
Você quer dizer um objeto mutável então.
No Python 3, as listas obtêm um
copy
método (em 2, você usaria uma fatia para fazer uma cópia):Cópias rasas
Cópias rasas são apenas cópias do recipiente mais externo.
list.copy
é uma cópia superficial:Você não recebe uma cópia dos objetos internos. Eles são o mesmo objeto - portanto, quando são mutados, a alteração aparece nos dois contêineres.
Cópias profundas
Cópias profundas são cópias recursivas de cada objeto interior.
As alterações não são refletidas no original, apenas na cópia.
Objetos imutáveis
Objetos imutáveis geralmente não precisam ser copiados. De fato, se você tentar, o Python fornecerá apenas o objeto original:
As tuplas nem sequer têm um método de cópia, então vamos tentar com uma fatia:
Mas vemos que é o mesmo objeto:
Da mesma forma para seqüências de caracteres:
e para frozensets, mesmo que eles tenham um
copy
método:Quando copiar objetos imutáveis
Objetos imutáveis devem ser copiados se você precisar de um objeto interior mutável copiado.
Como podemos ver, quando o objeto interior da cópia é alterado , o original não muda.
Objetos personalizados
Objetos personalizados geralmente armazenam dados em um
__dict__
atributo ou em__slots__
(uma estrutura de memória semelhante a uma tupla).Para criar um objeto copiável, defina
__copy__
(para cópias rasas) e / ou__deepcopy__
(para cópias profundas).Observe que
deepcopy
mantém um dicionário de memorizaçãoid(original)
(ou números de identidade) para cópias. Para ter bom comportamento com estruturas de dados recursivas, verifique se você ainda não fez uma cópia e, se tiver, devolva-a.Então, vamos criar um objeto:
E
copy
faz uma cópia superficial:E
deepcopy
agora faz uma cópia profunda:fonte
Cópia rasa com
copy.copy()
Cópia profunda com
copy.deepcopy()
Documentação: https://docs.python.org/3/library/copy.html
Testado em Python 3.6.5.
fonte
Eu acredito que o seguinte deve funcionar com muitos bem-comportados classificados em Python:
(É claro que não estou falando aqui de "cópias profundas", que é uma história diferente e que pode não ser um conceito muito claro - quão profunda é a profundidade suficiente?)
De acordo com meus testes com o Python 3, para objetos imutáveis, como tuplas ou cordas, ele retorna o mesmo objeto (porque não há necessidade de fazer uma cópia superficial de um objeto imutável), mas para listas ou dicionários ele cria uma cópia superficial independente .
Obviamente, esse método funciona apenas para classes cujos construtores se comportam de acordo. Possíveis casos de uso: fazendo uma cópia superficial de uma classe de contêiner Python padrão.
fonte
__init__
método deles . Então, eu pensei que este método pode ser bom o suficiente para certos fins. De qualquer forma, estarei interessado em comentários informativos sobre essa sugestão.class Foo(object): def __init__(self, arg): super(Foo, self).__init__() self.arg = arg
básico como ele recebe. Se eu fizerfoo = Foo(3) bar = copy(foo) print(foo.arg) # 3 print(bar.arg) # <__main__.Foo object at ...>
isso significa que suacopy
função está quebrada até para as classes mais básicas. Novamente, é um truque legal (portanto, não há DV), mas não é uma resposta.copy.copy
método para fazer cópias rasas, mas, talvez ingênuo, parece-me que deve ser da responsabilidade da classe fornecer um "construtor de cópias rasas". Nesse caso, por que não fornecer o mesmo kinf de interface que ele fazdict
elist
faz? Portanto, se sua classe deseja assumir a responsabilidade de copiar seus objetos, por que não adicionar umaif isinstance(arg, type(self))
cláusula__init__
?