2009-09-02 17 views
5

मूल्यांकन किया जाता है मैं न्यू-शैली वर्ग में उपवर्गीकरण और शब्दकोश अद्यतन के साथ एक अजीब समस्या मिली है:अजगर तरीके: डिफ़ॉल्ट पैरामीटर मान एक बार

Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on 
win32 
>>> class a(object): 
...  def __init__(self, props={}): 
...    self.props = props 
... 
>>> class b(a): 
...  def __init__(self, val = None): 
...    super(b, self).__init__() 
...    self.props.update({'arg': val}) 
... 
>>> class c(b): 
...  def __init__(self, val): 
...    super(c, self).__init__(val) 
... 
>>> b_inst = b(2) 
>>> b_inst.props 
{'arg': 2} 
>>> c_inst = c(3) 
>>> c_inst.props 
{'arg': 3} 
>>> b_inst.props 
{'arg': 3} 
>>> 

डिबग में, दूसरा कॉल में (c(3)) आप देख सकते हैं कि a कन्स्ट्रक्टर self.props{'arg': 2} के बराबर है, और उसके बाद b कन्स्ट्रक्टर को इसके बाद बुलाया जाता है, यह {'arg': 3} दोनों ऑब्जेक्ट्स के लिए बन जाता है!

भी कंस्ट्रक्टर्स बुला के आदेश है:

a, b # for b(2) 
    c, a, b # for c(3) 

आप b निर्माता में self.props = {'arg': val} साथ self.props.update() बदल देंगे, तो सब कुछ ठीक हो जाएगा, और उम्मीद

के रूप में लेकिन मैं वास्तव में जरूरत है कार्य करेगा अद्यतन करें

+0

क्या यह एक विरासत समस्या है, या "डिफ़ॉल्ट पैरामीटर मानों का मूल्यांकन एक बार" किया जाता है? –

+0

धन्यवाद, '{} 'के साथ' कोई नहीं 'के साथ बदलकर मेरी मदद की। –

+0

धन्यवाद, हांक, मैंने इस सवाल का नाम बदल दिया है ताकि –

उत्तर

9

props ऐसे ही एक डिफ़ॉल्ट मान नहीं करना चाहिए:

इस परिवर्तन यह करने के लिए ठीक करने के लिए। इसके बजाय इसे करें:

class a(object): 
    def __init__(self, props=None): 
     if props is None: 
      props = {} 
     self.props = props 

यह एक आम पायथन "gotcha" है।

7

आपकी समस्या इस पंक्ति में है:

def __init__(self, props={}): 

{} एक उत्परिवर्तनीय प्रकार है। और पायथन डिफ़ॉल्ट तर्क मानों में केवल एक बार मूल्यांकन किया जाता है। इसका मतलब है कि आपके सभी उदाहरण एक ही शब्दकोश वस्तु साझा कर रहे हैं!

class a(object): 
    def __init__(self, props=None): 
     if is None: 
      props = {} 
     self.props = props 
+0

"अगर प्रोप नहीं है" मत करो, तो एक बूलियन झूठा मूल्य उस रेखा को तोड़ सकता है –

+0

@ गोर्गापोर, आप सही हैं कोई भी अधिक सटीक नहीं है। मैं अपना जवाब ठीक कर दूंगा। –

1

लघु संस्करण:

class a(object): 
    def __init__(self, props=None): 
     self.props = props if props is not None else {} 

class b(a): 
    def __init__(self, val = None): 
     super(b, self).__init__() 
     self.props.update({'arg': val}) 

class c(b): 
    def __init__(self, val): 
    super(c, self).__init__(val) 

लंबे संस्करण:

समारोह परिभाषा, ठीक एक बार मूल्यांकन किया जाता है तो हर बार जब आप यह एक ही डिफ़ॉल्ट तर्क फोन प्रयोग किया जाता है ऐसा करें। इसके लिए आपके काम की अपेक्षा करने के लिए, किसी भी कार्य को बुलाए जाने पर डिफ़ॉल्ट तर्कों का मूल्यांकन किया जाना चाहिए। लेकिन इसके बजाय पाइथन एक फ़ंक्शन ऑब्जेक्ट उत्पन्न करता है और ऑब्जेक्ट में डिफ़ॉल्ट जोड़ता है (func_obj.func_defaults)

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