python - पायथन में** kwargs का उपयोग करने के लिए सही तरीका




(8)

** kwargs और डिफ़ॉल्ट मानों का उपयोग करना आसान है। कभी-कभी, हालांकि, आपको पहले स्थान पर ** kwargs का उपयोग नहीं करना चाहिए।

इस मामले में, हम वास्तव में ** kwargs का सबसे अच्छा उपयोग नहीं कर रहे हैं।

class ExampleClass( object ):
    def __init__(self, **kwargs):
        self.val = kwargs.get('val',"default1")
        self.val2 = kwargs.get('val2',"default2")

उपरोक्त एक "परेशान क्यों है?" घोषणा। यह वही है

class ExampleClass( object ):
    def __init__(self, val="default1", val2="default2"):
        self.val = val
        self.val2 = val2

जब आप ** kwargs का उपयोग कर रहे हैं, तो आपका मतलब है कि कोई कीवर्ड केवल वैकल्पिक नहीं है, बल्कि सशर्त है। सरल डिफ़ॉल्ट मानों से अधिक जटिल नियम हैं।

जब आप ** kwargs का उपयोग कर रहे हैं, तो आप आमतौर पर निम्न की तरह कुछ और मतलब करते हैं, जहां सरल डिफ़ॉल्ट लागू नहीं होते हैं।

class ExampleClass( object ):
    def __init__(self, **kwargs):
        self.val = "default1"
        self.val2 = "default2"
        if "val" in kwargs:
            self.val = kwargs["val"]
            self.val2 = 2*self.val
        elif "val2" in kwargs:
            self.val2 = kwargs["val2"]
            self.val = self.val2 / 2
        else:
            raise TypeError( "must provide val= or val2= parameter values" )

जब डिफ़ॉल्ट मानों की बात आती है तो पाइथन में **kwargs का उपयोग करने का उचित तरीका क्या है?

kwargs एक शब्दकोश देता है, लेकिन डिफ़ॉल्ट मान सेट करने का सबसे अच्छा तरीका क्या है, या कोई है? क्या मुझे इसे एक शब्दकोश के रूप में एक्सेस करना चाहिए? कार्य प्राप्त करें का प्रयोग करें?

class ExampleClass:
    def __init__(self, **kwargs):
        self.val = kwargs['val']
        self.val2 = kwargs.get('val2')

एक साधारण सवाल है, लेकिन एक है कि मुझे अच्छे संसाधन नहीं मिल रहे हैं। लोग कोड में इसे अलग-अलग तरीके से करते हैं जो मैंने देखा है और यह जानना मुश्किल है कि क्या उपयोग करना है।


@AbhinavGupta और @Steef update() का उपयोग करने का सुझाव दिया, जो मुझे बड़ी तर्क सूचियों को संसाधित करने के लिए बहुत उपयोगी पाया गया:

args.update(kwargs)

क्या होगा यदि हम यह जांचना चाहते हैं कि उपयोगकर्ता ने कोई नकली / असमर्थित तर्क पारित नहीं किया है? @ विनयसिपिप ने बताया कि pop() का उपयोग तर्कों की सूची को क्रमशः संसाधित करने के लिए किया जा सकता है। फिर, किसी भी बचे हुए तर्क नकली हैं। अच्छा लगा।

ऐसा करने का एक और संभावित तरीका यहां है, जो update() का उपयोग करने का सरल वाक्यविन्यास रखता है:

# kwargs = dictionary of user-supplied arguments
# args = dictionary containing default arguments

# Check that user hasn't given spurious arguments
unknown_args = user_args.keys() - default_args.keys()
if unknown_args:
    raise TypeError('Unknown arguments: {}'.format(unknown_args))

# Update args to contain user-supplied arguments
args.update(kwargs)

unknown_args एक ऐसा set जिसमें तर्कों के नाम होते हैं जो डिफ़ॉल्ट में नहीं होते हैं।


आप ऐसा कुछ कर सकते हैं

class ExampleClass:
    def __init__(self, **kwargs):
        arguments = {'val':1, 'val2':2}
        arguments.update(kwargs)
        self.val = arguments['val']
        self.val2 = arguments['val2']

आप करेंगे

self.attribute = kwargs.pop('name', default_value)

या

self.attribute = kwargs.get('name', default_value)

यदि आप pop उपयोग करते हैं, तो आप जांच सकते हैं कि कोई नकली मूल्य भेजा गया है या नहीं, और उचित कार्रवाई (यदि कोई हो) ले।


जबकि ज्यादातर उत्तर कह रहे हैं कि, उदाहरण के लिए,

def f(**kwargs):
    foo = kwargs.pop('foo')
    bar = kwargs.pop('bar')
    ...etc...

के समान है"

def f(foo=None, bar=None, **kwargs):
    ...etc...

यह सच नहीं है। बाद के मामले में, f को f(23, 42) कहा जा सकता है, जबकि पूर्व मामला केवल तर्कों को स्वीकार करता है - कोई स्थितित्मक कॉल नहीं। अक्सर आप कॉलर को अधिकतम लचीलापन की अनुमति देना चाहते हैं और इसलिए दूसरा फॉर्म, जैसा कि अधिकांश उत्तरों का दावा है, बेहतर है: लेकिन यह हमेशा मामला नहीं है। जब आप कई वैकल्पिक मानकों को स्वीकार करते हैं, जिनमें से केवल कुछ ही पास किए जाते हैं, तो यह एक उत्कृष्ट विचार हो सकता है (आपके कॉल साइटों पर दुर्घटनाओं और अपठनीय कोड से बचें!) नामित तर्कों के उपयोग को मजबूर करने के लिए - threading.Threadthreading.Thread एक उदाहरण है। पहला रूप यह है कि आप इसे पायथन 2 में कैसे कार्यान्वित करते हैं।

मुहावरे इतना महत्वपूर्ण है कि पाइथन 3 में अब विशेष समर्थन वाक्यविन्यास है: def हस्ताक्षर में एकल * बाद प्रत्येक तर्क केवल कीवर्ड है, यानी, एक स्थितित्मक तर्क के रूप में पारित नहीं किया जा सकता है, लेकिन केवल नामित एक के रूप में। तो पायथन 3 में आप उपरोक्त कोड को कोड कर सकते हैं:

def f(*, foo=None, bar=None, **kwargs):
    ...etc...

दरअसल, पायथन 3 में आपके पास कीवर्ड-केवल तर्क भी हो सकते हैं जो वैकल्पिक नहीं हैं (डिफ़ॉल्ट मान वाले बिना)।

हालांकि, पाइथन 2 में अभी भी लंबे समय तक उत्पादक जीवन है, इसलिए तकनीक और मुहावरे को भूलना बेहतर नहीं है जो आपको पाइथन 2 महत्वपूर्ण डिजाइन विचारों में लागू करने दें जो सीधे पायथन 3 में भाषा में समर्थित हैं!


मुझे लगता है कि जब डिफ़ॉल्ट मानों की बात आती है तो पाइथन में **kwargs का उपयोग करने का उचित तरीका नीचे दी गई विधि विधि setdefault का उपयोग करना है:

class ExampleClass:
    def __init__(self, **kwargs):
        kwargs.setdefault('val', value1)
        kwargs.setdefault('val2', value2)

इस तरह, यदि कोई उपयोगकर्ता कीवर्ड तर्क में 'वैल' या 'val2' पास करता है, तो उनका उपयोग किया जाएगा; अन्यथा, सेट किए गए डिफ़ॉल्ट मानों का उपयोग किया जाएगा।


यदि आप इसे * तर्क के साथ जोड़ना चाहते हैं तो आपको परिभाषा के अंत में * args और ** kwargs रखना होगा।

इसलिए:

def method(foo, bar=None, *args, **kwargs):
    do_something_with(foo, bar)
    some_other_function(*args, **kwargs)

यहां एक और दृष्टिकोण है:

def my_func(arg1, arg2, arg3):
    ... so something ...

kwargs = {'arg1': 'Value One', 'arg2': 'Value Two', 'arg3': 'Value Three'}
# Now you can call the function with kwargs like this:

my_func(**kwargs)






kwargs