2012-05-16 33 views
8

我想實現一個符號類型,它跟蹤我們已有的符號(保存在_sym_table),並返回它們(如果它們存在)否則新的。代碼: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__() 

但是,當我打電話copy.deepcopy這樣Symbol實例的名單上,引發異常:

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__方法。

0

定義__getnewargs__ - 這樣你不僅能夠copydeepcopy,但你也可以pickle

相關問題