2009-10-18 10 views
24

दोस्तों, मैं अभी हाल ही में अजगर शुरू कर दिया और वैकल्पिक पैरामीटर के साथ भ्रमित हो, मैं इस तरह कार्यक्रम है कहना उनकेअजगर वैकल्पिक पैरामीटर

print b.builds 
print c.builds 

मैंने पाया कि वे,

वास्तव में एक ही वस्तु का उपयोग कर रहे बनाता है
<__main__.B instance at 0x68ee0> 
<__main__.B instance at 0x68ee0> 

लेकिन यह नहीं है कि मैं, क्या चाहते हैं के बाद से यदि b बनाता है के कुछ आंतरिक स्थिति बदल गया है, c वस्तु में एक भी बदल जाएगा।

क्या यह वैकल्पिक पैरामीटर वाक्यविन्यास का उपयोग कर हर बार इस वैकल्पिक पैरामीटर को फिर से बनाना संभव है?

+15

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

+0

पाइथन में ["कम अस्थिरता" के संभावित डुप्लिकेट: म्यूटेबल डिफ़ॉल्ट तर्क] (http://stackoverflow.com/ प्रश्न/1132 9 41/कम-आश्चर्य-इन-पायथन-द-म्यूटेबल-डिफॉल्ट-तर्क) –

उत्तर

6

हां; डिफ़ॉल्ट मानकों का मूल्यांकन उस समय किया जाता है जब फ़ंक्शन परिभाषित किया जाता है।

एक संभव समाधान पैरामीटर वर्ग बजाय एक उदाहरण, एक ला

def foo(blah, klass = B): 
    b = klass() 
    # etc 
+0

संक्षेप में, आप एक परिवर्तनीय ऑब्जेक्ट को डिफ़ॉल्ट मान के रूप में उपयोग नहीं कर सकते हैं। –

+0

निश्चित रूप से आप कर सकते हैं। कक्षाएं पाइथन में उत्परिवर्तनीय हैं। इसमें परिवर्तनीय/अपरिवर्तनीय के साथ कुछ लेना देना नहीं है। –

+0

एक परिवर्तनीय वस्तु का उपयोग इस प्रश्न में सटीक भ्रम की ओर जाता है। जब आप किसी वर्ग को डिफॉल्ट के रूप में उपयोग करते हैं तो आप ऑब्जेक्ट बनाने के लिए लगभग हमेशा तत्काल होते हैं। कक्षा की उत्परिवर्तन कोई फर्क नहीं पड़ता क्योंकि आप कक्षा का उपयोग सीधे उसी तरह से नहीं कर रहे हैं जिस तरह से आप किसी सूची या शब्दकोश का उपयोग करते हैं। –

15

आप निम्नलिखित करने की ज़रूरत हो के लिए होगा:

class A: 
    def __init__(self, builds=None): 
     if builds is None: 
      builds = B() 
     self.builds = builds 

यह एक बहुत व्यापक है एक डिफ़ॉल्ट तर्क के रूप में mutable पैरामीटर का उपयोग कर, स्प्रेड त्रुटि। एसओ पर शायद बहुत सारे डुप्ले हैं।

+1

तो चलिए एक डुप्ली ढूंढें और इसे बंद करें? –

+2

समस्या यह है: आप परिवर्तनीय ऑब्जेक्ट्स को डिफ़ॉल्ट मानों के रूप में उपयोग नहीं कर सकते हैं। पिछले डुप्लीकेट्स ने सभी सूचियों का उपयोग करने की कोशिश की है। यह ऑब्जेक्ट का उपयोग करने वाला पहला है। एक परिवर्तनीय वस्तु को डिफ़ॉल्ट मान के रूप में उपयोग करने का प्रयास करने की "मानक समस्या" है। –

46

आपको समझने की आवश्यकता है कि उन्हें प्रभावी ढंग से उपयोग करने के लिए डिफ़ॉल्ट मान कैसे काम करते हैं।

कार्य ऑब्जेक्ट्स हैं। इस प्रकार, उनके पास विशेषताएं हैं। इसलिए, यदि मैं यह फ़ंक्शन बनाता हूं:

>>> def f(x, y=[]): 
     y.append(x) 
     return y 

मैंने एक ऑब्जेक्ट बनाया है।

>>> dir(f) 
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', 
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',  
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 
'func_name'] 

उनमें से एक func_defaults है: यहाँ अपनी विशेषताएँ हैं। यह वादा करता है, वहां क्या है?

>>> f.func_defaults 
([],) 

यह एक टुपल है जिसमें फ़ंक्शन के डिफ़ॉल्ट मान होते हैं। यदि कोई डिफ़ॉल्ट मान एक ऑब्जेक्ट है, तो टुपल में उस ऑब्जेक्ट का एक उदाहरण होता है।

यह काफी कुछ counterintuitive व्यवहार की ओर जाता है अगर आप सोच रहे हैं f एक सूची में कोई आइटम जोड़ता है कि, केवल उस आइटम वाली एक सूची लौट रहा है, तो कोई सूची प्रदान की जाती है:

>>> f(1) 
[1] 
>>> f(2) 
[1, 2] 

लेकिन अगर आप जानते हैं कि डिफ़ॉल्ट मान एक वस्तु उदाहरण है कि समारोह के गुणों में से एक में संग्रह किया गया है है, यह बहुत कम counterintuitive है:

>>> x = f(3) 
>>> y = f(4) 
>>> x == y 
True 
>>> x 
[1, 2, 3, 4] 
>>> x.append(5) 
>>> f(6) 
[1, 2, 3, 4, 5, 6] 

यह जानने के बाद, यह स्पष्ट है कि अगर आप चाहते हैं एक नई सूची होने के लिए एक समारोह के पैरामीटर का डिफ़ॉल्ट मान (या कोई नया ओबी जेक्ट), आप आसानी से func_defaults में ऑब्जेक्ट का एक उदाहरण छीन नहीं सकते हैं। जब भी फ़ंक्शन को कॉल किया जाता है तो आपको एक नया निर्माण करना होगा:

>>>def g(x, y=None): 
     if y==None: 
      y = [] 
     y.append(x) 
     return y