2010-05-21 11 views
8

कोड:पायथन बेस क्लास विशेषताएँ साझा करते हैं? test.py में

class Base(object): 
    def __init__(self, l=[]): 
     self.l = l 

    def add(self, num): 
     self.l.append(num) 

    def remove(self, num): 
     self.l.remove(num) 

class Derived(Base): 
    def __init__(self, l=[]): 
     super(Derived, self).__init__(l) 

अजगर खोल सत्र:

Python 2.6.5 (r265:79063, Apr 1 2010, 05:22:20) 
[GCC 4.4.3 20100316 (prerelease)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import test 
>>> a = test.Derived() 
>>> b = test.Derived() 
>>> a.l 
[] 
>>> b.l 
[] 
>>> a.add(1) 
>>> a.l 
[1] 
>>> b.l 
[1] 
>>> c = test.Derived() 
>>> c.l 
[1] 

मैं "सी ++ - तरह" उम्मीद कर रहा था व्यवहार है, जिसमें प्रत्येक व्युत्पन्न वस्तु आधार वर्ग के अपने स्वयं के उदाहरण में शामिल है। क्या अभी भी यही मामला है? प्रत्येक ऑब्जेक्ट एक ही सूची उदाहरण साझा करने के लिए क्यों दिखाई देता है?

+0

संभव डुप्लिकेट (http://stackoverflow.com/questions/1132941/least-astonishment-in-python- द म्यूटेबल-डिफॉल्ट-तर्क) –

उत्तर

14

आप एक सामान्य पायथन नवागंतुक गलती कर रहे हैं। How should I declare default values for instance variables in Python?

संक्षेप में बताया गया है, अजगर वर्ग परिभाषाएँ एक बार केवल व्याख्या:

मेरे यहाँ उत्तर देखें। इसका मतलब है कि __init__() विधि में घोषित सब कुछ केवल एक बार बनाया गया है। या, दूसरे शब्दों में, आपकी [] सूची डिफ़ॉल्ट तर्क केवल एक बार बनाया जाता है।

फिर self.l = l एक ही उदाहरण के लिए एक संदर्भ आप एक नया वर्ग बनाने हर बार, इसलिए व्यवहार आप की अपेक्षा नहीं थी प्रदान करती है।

pythonic तरीका यह (आंशिक कोड) है:

def __init__(self, arg=None): 
    if arg is None: 
     arg = [] 
    self.arg = arg 

इसके अलावा, आप l तुलना में एक बेहतर नामकरण परंपरा है, जो पढ़ने के लिए कठिन है उपयोग करने पर विचार करना चाहिए और 1 या | के रूप में गलत हो सकता है।

+0

+1 सही उत्तर के लिए +1 है, लेकिन कम से कम संक्षेप में इसे यहां वर्तनी करना अच्छा लगेगा। – Etaoin

+1

मैं तब करूँगा। ':]' –

+0

जाहिर है, यह एक परीक्षण स्निपेट है। मैं एक चर नाम के रूप में 'एल' कभी नहीं चुनूंगा। – tad

2

इसे म्यूटेबल डिफ़ॉल्ट तर्क बग कहा जाता है जिसे आमतौर पर पाइथन के लिए नए लोगों द्वारा बनाया जाता है। जब आप एक डिफ़ॉल्ट तर्क के रूप में एक म्यूटेबल देते हैं, तो उसी ऑब्जेक्ट को उदाहरणों में उपयोग किया जाता है जब डिफ़ॉल्ट तर्क का उपयोग करने की आवश्यकता होती है। एक बेहतर ढंग से समझने http://docs.python.org/tutorial/controlflow.html#default-argument-values

में महत्वपूर्ण चेतावनी अनुभाग की जांच अपने कोड में, उदाहरण के लिए एक प्रयोग किया जाता परिवर्तनशील डिफ़ॉल्ट तर्क (एक खाली सूची वस्तु) में यह init कॉल है मिलता है और जब आप ख के कहने, बनाया जो बदले में बेस की इनिट विधि कहा जाता है, फिर से उसी वस्तु का उपयोग किया जाता है जिसका उपयोग इसके init में किया जाता है। सरल शब्दों पर a.l और b.l एक ही सूची ऑब्जेक्ट को इंगित करता है।

एक बहुत ही इसी तरह की चर्चा - "Least Astonishment" and the Mutable Default Argument

[ "कम से कम विस्मय" पायथन में: परिवर्त्य डिफ़ॉल्ट तर्क] की
+0

यह एक बग नहीं है, यह भाषा काम करता है। –

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