2012-05-16 2 views
8

이미있는 심볼을 추적하고 (_sym_table에 저장되어있는) 심볼 유형을 구현하고이를 반환하거나 새로운 것들. 코드 : 나는 그런 Symbol 인스턴스 목록에 copy.deepcopy를 호출 할 때, 예외가 발생copy.deepcopy는 자체 정의 된 __new __() 메서드를 사용하여 객체에 TypeError를 발생시킵니다.

# -*- coding: utf-8 -*- 

_sym_table = {} 

class Symbol(object): 
    def __new__(cls, sym): 
     if sym not in _sym_table: 
      return super().__new__(cls) 
     else: 
      return _sym_table[sym] 

    def __init__(self, sym): 
     self.sym = sym 
     _sym_table[sym] = self 

    def __str__(self): 
     return self.sym 

    def __cmp__(self, other): 
     return self is other 

    def __hash__(self): 
     return self.sym.__hash__() 

:

a = Symbol('a') 
b = Symbol('b') 
s = [a, b] 
t = copy.deepcopy(s) 

오류 메시지 :

Traceback (most recent call last): 
    File "xxx.py", line 7, in <module> 
    t = copy.deepcopy(s) 
    File "/usr/lib/python3.2/copy.py", line 147, in deepcopy 
    y = copier(x, memo) 
    File "/usr/lib/python3.2/copy.py", line 209, in _deepcopy_list 
    y.append(deepcopy(a, memo)) 
    File "/usr/lib/python3.2/copy.py", line 174, in deepcopy 
    y = _reconstruct(x, rv, 1, memo) 
    File "/usr/lib/python3.2/copy.py", line 285, in _reconstruct 
    y = callable(*args) 
    File "/usr/lib/python3.2/copyreg.py", line 88, in __newobj__ 
    return cls.__new__(cls, *args) 
TypeError: __new__() takes exactly 2 arguments (1 given) 

그래서 제 질문은 다음과 같습니다

  • H 내가 정의한 __new__ 메소드를 사용하여이 오브젝트들에 깊은 복사를 할 수 있습니까?
  • copy.deepcopy을 언제 어떻게 사용할 수 있습니까?

감사합니다.

답변

5

deepcopycopy은 어떤 인수가 __new__으로 전달되는지 알 수 없기 때문에 생성자 인수가 필요없는 클래스에서만 작동합니다.

__init__ 인수를 사용할 수있는 이유는 개체를 복사 할 때 __init__이 호출되지 않지만 __new__을 호출하여 새 개체를 만들어야한다는 것입니다. 당신이 복사를 제어하려는 경우

그래서, 당신은 특별한 __copy____deepcopy__ 방법을 정의해야합니다 : 그런데

def __copy__(self): 
    return self 

def __deepcopy__(self, memo): 
    return self 

singletonsevil하고 정말 파이썬에 필요하지 않습니다.

1

Symbol 인스턴스가 싱글 톤이되기를 원합니다. 그러나 Deepcopy는 인스턴스의 정확한 사본, 즉 원래 인스턴스와 다른 인스턴스를 원할 때 사용하기로되어 있습니다.

그래서 여기에서 사용법은 딥 카피의 목적과 다소 모순됩니다. 아무튼 작동하게하려면 Symbol__deepcopy__ 메서드를 정의 할 수 있습니다.

0

__getnewargs__을 정의하면 copydeepcopy 일뿐만 아니라 pickle도 가능합니다.

관련 문제