복붙노트

[PYTHON] 파이썬 클래스를 복사하는 방법?

PYTHON

파이썬 클래스를 복사하는 방법?

copy의 deepcopy는 클래스를 복사하지 않습니다 :

>>> class A(object):
>>>     ARG = 1

>>> B = deepcopy(A)

>>> A().ARG
>>> 1

>>> B().ARG
>>> 1

>>> A.ARG = 2

>>> B().ARG
>>> 2

그것은 유일한 방법일까요?

B(A):
    pass

해결법

  1. ==============================

    1.일반적으로 다른 포스터가 이미 지적한 것처럼 상속은 올바른 방법입니다.

    일반적으로 다른 포스터가 이미 지적한 것처럼 상속은 올바른 방법입니다.

    그러나, 당신이 정말로 같은 이름을 가진 다른 타입을 상속받지 않고 다시 만들고 싶다면 다음과 같이 할 수 있습니다 :

    class B(object):
        x = 3
    
    CopyOfB = type('CopyOfB', B.__bases__, dict(B.__dict__))
    
    b = B()
    cob = CopyOfB()
    
    print b.x   # Prints '3'
    print cob.x # Prints '3'
    
    b.x = 2
    cob.x = 4
    
    print b.x   # Prints '2'
    print cob.x # Prints '4'
    

    변경할 수있는 속성 값에주의해야합니다.

    class C(object):
        x = []
    
    CopyOfC = type('CopyOfC', C.__bases__, dict(C.__dict__))
    
    c = C()
    coc = CopyOfC()
    
    c.x.append(1)
    coc.x.append(2)
    
    print c.x   # Prints '[1, 2]' (!)
    print coc.x # Prints '[1, 2]' (!)
    
  2. ==============================

    2.클래스를 "복사"하는 올바른 방법은 상속으로 추측 할 수 있습니다.

    클래스를 "복사"하는 올바른 방법은 상속으로 추측 할 수 있습니다.

    class B(A):
        pass
    
  3. ==============================

    3.팩토리 함수를 사용할 수 있습니다.

    팩토리 함수를 사용할 수 있습니다.

    def get_A():
        class A(object):
            ARG = 1
        return A
    
    A = get_A()
    B = get_A()
    
  4. ==============================

    4.여기서 정적 변수의 의미를 오해 한 것 같습니다. self.some_thing이 아닌 메소드 외부에서 변수를 선언 할 때마다 변수는 클래스의 정적 변수로 간주됩니다 (예 : 여기 ARG 변수). 따라서 정적 변수를 변경하는 클래스의 모든 객체 (인스턴스)는 동일한 클래스의 다른 모든 객체를 변경하게됩니다. deepcopy가 실제로 여기서 일을합니다.

    여기서 정적 변수의 의미를 오해 한 것 같습니다. self.some_thing이 아닌 메소드 외부에서 변수를 선언 할 때마다 변수는 클래스의 정적 변수로 간주됩니다 (예 : 여기 ARG 변수). 따라서 정적 변수를 변경하는 클래스의 모든 객체 (인스턴스)는 동일한 클래스의 다른 모든 객체를 변경하게됩니다. deepcopy가 실제로 여기서 일을합니다.

  5. ==============================

    5.나만의 생성자를 만들고 원래 클래스를 만든 방법을 복제하십시오.

    나만의 생성자를 만들고 원래 클래스를 만든 방법을 복제하십시오.

    class MyClass(object):
        def __init__(self, **kw):
            self.kw = kw
            self.__dict__.update(kw)
    
        def copy(self):
            return MyClass(**self.kw)
    

    하지만 먼저 개체를 복사해야 할 필요가 없습니다.

    sidenote : 다음과 같이 도망 갈 수도 있습니다.

    B = deepcopy(A)
    B.__dict__ = deepcopy(A.__dict__)
    

    그러나 이것은 아마도 매우 잘못된 것이며 당신은 이것을해서는 안됩니다. 편집 : 실제로 AttributeError : 'dictproxy'객체에는 OP에 따라 'update'속성이 없습니다.

  6. ==============================

    6.플로리안 브루 커 (Florian Brucker)가 지적했듯이, 변경 가능한 클래스 속성에는 문제가 있습니다. 또한 새로운 스타일의 오브젝트를 딥 카피 (cls .__ dict__) 할 수 없습니다. 나는 내가하고있는 일에 대해이 문제를 해결하기 위해 다음을 수행했다. 나는 충분히 결정된 누군가가 이것을 깨뜨릴 수 있다고 확신한다. 그러나 더 많은 경우에 효과가 있습니다.

    플로리안 브루 커 (Florian Brucker)가 지적했듯이, 변경 가능한 클래스 속성에는 문제가 있습니다. 또한 새로운 스타일의 오브젝트를 딥 카피 (cls .__ dict__) 할 수 없습니다. 나는 내가하고있는 일에 대해이 문제를 해결하기 위해 다음을 수행했다. 나는 충분히 결정된 누군가가 이것을 깨뜨릴 수 있다고 확신한다. 그러나 더 많은 경우에 효과가 있습니다.

    from copy import deepcopy
    from typing import TypeVar
    
    Cls = TypeVar('Cls')
    
    
    # This type hint is a dirty lie to make autocomplete and static
    # analyzers give more useful results. Crazy the stuff you can do
    # with python...
    def copy_class(cls: Cls) -> Cls:
        copy_cls = type(f'{cls.__name__}Copy', cls.__bases__, dict(cls.__dict__))
        for name, attr in cls.__dict__.items():
            try:
                hash(attr)
            except TypeError:
                # Assume lack of __hash__ implies mutability. This is NOT
                # a bullet proof assumption but good in many cases.
                setattr(copy_cls, name, deepcopy(attr))
        return copy_cls
    
    
    def test_copy_class():
        class A(object):
            mutable_class_var = []
    
        ACopy = copy_class(A)
    
        a = A()
        acopy = ACopy()
    
        acopy.mutable_class_var.append(1)
        assert a.mutable_class_var == []
        assert A.mutable_class_var == []
        assert ACopy.mutable_class_var == [1]
        assert acopy.mutable_class_var == [1]
    
  7. ==============================

    7.클래스의 다른 인스턴스를 만들고 싶다면 다음과 같이하십시오.

    클래스의 다른 인스턴스를 만들고 싶다면 다음과 같이하십시오.

     >>> class A(object):
    ...    ARG=1
    ... 
     >>> a = A()
     >>> A().ARG
     1
     >>> b = A()
     >>> b.ARG
     1
     >>> a.ARG=2
     >>> b.ARG
     1
    
  8. from https://stackoverflow.com/questions/9541025/how-to-copy-a-python-class by cc-by-sa and MIT license