python / python/cpython

`copy.copy` ignores methods of the object which are not part of the class

Aberta
#132,272 3 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib type-bug
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

Bug report

Bug description:
from types import MethodType
from copy import copy, deepcopy

class MyClass:
    def __copy__(self):
        print("Call __copy__ of class")
        return self

    def __deepcopy__(self, memo):
        print("Call __deepcopy__ of class")
        return self

obj1 = MyClass()
obj2 = MyClass()

def copy_func(self):
    print("New copy function")
    return self

def deepcopy_func(self, memo):
    print("New deepcopy function")
    return self

obj11 = copy(obj1)
# > Call __copy__ of class
obj12 = deepcopy(obj1)
# > Call __deepcopy__ of class

obj21 = copy(obj2)
# > Call __copy__ of class
obj22 = deepcopy(obj2)
# > Call __deepcopy__ of class

obj1.__copy__ = copy_func.__get__(obj1)
obj1.__deepcopy__ = deepcopy_func.__get__(obj1)

obj2.__copy__ = MethodType(copy_func, obj2)
obj2.__deepcopy__ = MethodType(deepcopy_func, obj2)

obj13 = copy(obj1)
# > Call __copy__ of class
obj14 = deepcopy(obj1)
# > New deepcopy function

obj23 = copy(obj2)
# > Call __copy__ of class
obj24 = deepcopy(obj2)
# > New deepcopy function

Knowing, that binding additional methods to an object after instantiation might not be recommended, the behavior shown above confuses me. My expectation is that copy.copy and copy.deepcopy both use the __copy__/__deepcopy__ method of the actual object passed to it (code). However, copy.copy does not, but rather uses the __copy__ method of the class which could be different from that of the object (code).

Historically, the behavior of copy.copy and copy.deepcopy was first identical (c06e3acc735a6e9cf28d0f511493bcfd8829117d, using the method of the class in both cases), but lateron changed (e690883ccf8081e5baab0e9d71f596f26245b569).

Apart from the differences between the behavior of copy.copy and copy.deepcopy w.r.t. the __copy__/__deepcopy__ methods, the copy.copy method itself takes two different approaches when looking for methods to create the copy: __copy__ is searched inside the class, and in case it is not found, the __reduce_ex__/__reduce__ are looked up in the object (code).

CPython versions tested on:

3.11

Operating systems tested on:

Linux

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece por Lib/copy.py, nos caminhos de copy e de busca de redução vinculados no relatório, e então execute o reproducer fornecido na versão compatível do Python. Revise os commits históricos mencionados para entender por que copy.copy e copy.deepcopy divergiram. Considera-se concluído quando o comportamento dos métodos copy e deepcopy vinculados à instância estiver resolvido de forma consistente e coberto por um teste de regressão apropriado.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
backend
Tipo de issue
Bug
Dificuldade
5/5
Tempo estimado
Mais de uma semana
Status de atividade
Estagnada
Clareza
Razoavelmente clara
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.