2012-05-16 13 views
8

के साथ ऑब्जेक्ट्स पर TypeError उठाता है, मैं एक प्रतीक प्रकार को कार्यान्वित करना चाहता हूं, जो हमारे पास पहले से मौजूद प्रतीकों का ट्रैक रखता है (_sym_table में सहेजा गया), और यदि वे मौजूद हैं, या उन्हें बनाते हैं अन्यथा अन्यथा। कोड:copy.deepcopy स्वयं परिभाषित __new __() विधि

# -*- 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__() 

लेकिन जब मैं इस तरह के Symbol उदाहरणों की एक सूची पर copy.deepcopy कहते हैं, अपवाद उठाया है:

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) 

तो मेरी प्रश्न हैं:

  • एच क्या मैं इन वस्तुओं पर स्वयं परिभाषित __new__ विधियों के साथ एक गहरी प्रतिलिपि बना सकता हूं?
  • और copy.deepcopy का उपयोग कब और कैसे करें के बारे में कोई सुझाव?

बहुत बहुत धन्यवाद!

उत्तर

5

एक समस्या यह है कि deepcopy और copy को यह जानने का कोई तरीका नहीं है कि __new__ पर कौन से तर्क पास हैं, इसलिए वे केवल उन वर्गों के साथ काम करते हैं जिन्हें कन्स्ट्रक्टर तर्कों की आवश्यकता नहीं होती है।

कारण है कि आप __init__ तर्क हो सकता है कि __init__ जब एक वस्तु को कॉपी नहीं कहा जाता है, लेकिन __new__ नई वस्तु बनाने के लिए बुलाया जाना चाहिए।

ताकि आप नकल पर नियंत्रण करना चाहते हैं, तो आप विशेष __copy__ और __deepcopy__ पद्धतियां निर्धारित करना होगा:

def __copy__(self): 
    return self 

def __deepcopy__(self, memo): 
    return self 

वैसे, singletonsevil कर रहे हैं और वास्तव में अजगर में की जरूरत नहीं।

1

मुझे लगता है कि आप प्रतीक उदाहरण सिंगलटन होना चाहते हैं। हालांकि, दीपकोपी का उपयोग तब किया जाना चाहिए जब आप किसी इंस्टेंस की सटीक प्रतिलिपि चाहते हों, यानी एक अलग उदाहरण जो मूल के बराबर है।

तो यहां उपयोग गहराई के उद्देश्य के विपरीत है। यदि आप इसे किसी भी तरह से काम करना चाहते हैं, तो आप विधि पर हस्ताक्षर पर परिभाषित कर सकते हैं।

0

__getnewargs__ परिभाषित करें - इस तरह से आप केवल copy और deepcopy करने में सक्षम नहीं होगा, लेकिन आप यह भी pickle कर सकेंगे।

संबंधित मुद्दे