उत्तर की बहुत सारी जानकारी के बहुत कम टुकड़े हैं, इसलिए मैं इसे अपने पसंदीदा पैटर्न (ओं) के साथ लाना चाहता हूं।
डिफ़ॉल्ट मान एक mutableप्रकार है
यदि डिफ़ॉल्ट मान एक परिवर्तनशील वस्तु है, तो आप भाग्यशाली हैं: आप इस तथ्य का फायदा उठा सकते हैं कि पायथन के डिफ़ॉल्ट तर्कों का मूल्यांकन एक बार किया जाता है जब फ़ंक्शन को परिभाषित किया जाता है (अंतिम अनुभाग में उत्तर के अंत में इसके बारे में कुछ और)
इसका मतलब है कि आप आसानी से डिफ़ॉल्ट म्यूटेबल वैल्यू की तुलना करके isदेख सकते हैं कि क्या इसे एक तर्क के रूप में पारित किया गया था या डिफ़ॉल्ट रूप से छोड़ा गया था, जैसा कि निम्न उदाहरणों में फ़ंक्शन या विधि के रूप में है:
def f(value={}):
if value is f.__defaults__[0]:
print('default')
else:
print('passed in the call')
तथा
class A:
def f(self, value={}):
if value is self.f.__defaults__[0]:
print('default')
else:
print('passed in the call')
अपरिवर्तनीय डिफ़ॉल्ट तर्क
अब, यह थोड़ा कम सुरुचिपूर्ण है यदि आपके डिफ़ॉल्ट को एक immutableमूल्य होने की उम्मीद है (और याद रखें कि तार भी अपरिवर्तनीय हैं!) क्योंकि आप चाल का फायदा नहीं उठा सकते हैं क्योंकि यह है, लेकिन अभी भी कुछ है जो आप कर सकते हैं, अभी भी उत्परिवर्ती का शोषण कर रहे हैं प्रकार; मूल रूप से आप फ़ंक्शन सिग्नेचर में एक म्यूट "नकली" डिफ़ॉल्ट, और फ़ंक्शन बॉडी में वांछित "वास्तविक" डिफ़ॉल्ट मान डालते हैं ।
def f(value={}):
"""
my function
:param value: value for my function; default is 1
"""
if value is f.__defaults__[0]:
print('default')
value = 1
else:
print('passed in the call')
print(value)
यदि आप वास्तविक डिफ़ॉल्ट हैं तो यह विशेष रूप से मज़ेदार लगता है None, लेकिन Noneअपरिवर्तनीय है इसलिए ... आपको अभी भी फ़ंक्शन डिफ़ॉल्ट पैरामीटर के रूप में स्पष्ट रूप से एक उत्परिवर्ती का उपयोग करने की आवश्यकता है, और कोड में कोई भी नहीं स्विच करें।
Defaultअपरिवर्तनीय चूक के लिए एक वर्ग का उपयोग करना
या, @cz सुझाव के समान, यदि अजगर डॉक्स पर्याप्त नहीं हैं :-), तो आप एपीआई को अधिक स्पष्ट करने के लिए (डॉक्स को पढ़े बिना) बनाने के लिए बीच में एक ऑब्जेक्ट जोड़ सकते हैं; used_proxy_ डिफ़ॉल्ट श्रेणी का उदाहरण परिवर्तनशील है, और इसमें वह वास्तविक डिफ़ॉल्ट मान होगा जिसका आप उपयोग करना चाहते हैं।
class Default:
def __repr__(self):
return "Default Value: {} ({})".format(self.value, type(self.value))
def __init__(self, value):
self.value = value
def f(default=Default(1)):
if default is f.__defaults__[0]:
print('default')
print(default)
default = default.value
else:
print('passed in the call')
print("argument is: {}".format(default))
अभी:
>>> f()
default
Default Value: 1 (<class 'int'>)
argument is: 1
>>> f(2)
passed in the call
argument is: 2
उपरोक्त अच्छी तरह से भी काम करता है Default(None)।
अन्य पैटर्न
जाहिर है कि उपरोक्त पैटर्न उन सभी की वजह से बदसूरत दिखते printहैं , जो केवल यह दिखाने के लिए हैं कि वे कैसे काम करते हैं। अन्यथा मैं उन्हें पर्याप्त और दोहरावदार पाता हूं।
आप __call__@dmg द्वारा सुझाए गए पैटर्न को अधिक सुव्यवस्थित तरीके से जोड़ने के लिए एक डेकोरेटर लिख सकते हैं , लेकिन यह अभी भी फ़ंक्शन परिभाषा में अजीब चाल का उपयोग करने के लिए बाध्य होगा - आपको इसे अलग करने की आवश्यकता होगी valueऔर value_defaultयदि आपके कोड को उन्हें अलग करने की आवश्यकता है, तो मुझे बहुत फायदा नहीं दिख रहा है और मैं उदाहरण नहीं लिखूंगा :-)
पायथन में डिफ़ॉल्ट मानों के रूप में पारस्परिक प्रकार
# 1 अजगर गोथा के बारे में थोड़ा और अधिक ! , ऊपर अपने आनंद के लिए गाली दी। आप यह देख सकते हैं कि मूल्यांकन के कारण क्या होता है :
def testme(default=[]):
print(id(default))
आप testme()जितनी बार चाहें दौड़ सकते हैं, आप हमेशा एक ही डिफ़ॉल्ट उदाहरण के संदर्भ देखेंगे (इसलिए मूल रूप से आपका डिफ़ॉल्ट अपरिवर्तनीय है :-))।
याद रखें अजगर में देखते हैं कि केवल 3 परिवर्तनशील में निर्मित प्रकार : set, list, dict, बाकी सब कुछ - यहां तक कि तार! - अपरिवर्तनीय है।