python - **(डबल स्टार/तारांकन) और*(स्टार/तारांकन) पैरामीटर के लिए क्या करता है?




syntax parameter-passing (10)

पैरामीटर के लिए ** (डबल स्टार) और * (स्टार) क्या करता है

वे कार्यों को स्वीकार करने के लिए परिभाषित करने की अनुमति देते हैं और उपयोगकर्ताओं के लिए किसी भी तर्क, स्थितित्मक ( * ) और कीवर्ड ( ** ) को पास करने की अनुमति देते हैं।

कार्य परिभाषित करना

*args तर्क वैकल्पिक स्थितित्मक तर्कों (पैरामीटर) की किसी भी संख्या के लिए अनुमति देता है, जिसे तर्क वाले नामों के लिए आवंटित किया जाएगा।

**kwargs वैकल्पिक कीवर्ड तर्कों (पैरामीटर) की किसी भी संख्या के लिए अनुमति देता है, जो कि kwargs नामक एक निर्देश में होगा।

आप किसी भी उपयुक्त नाम का चयन कर सकते हैं (और चाहिए), लेकिन यदि तर्क गैर-विशिष्ट अर्थशास्त्र के तर्कों के लिए है, तो तर्क और kwargs मानक नाम हैं।

विस्तार, किसी भी संख्या में तर्क पारित करना

आप क्रमशः सूचियों (या किसी भी पुनरावृत्त) और dicts (या किसी भी मैपिंग) से पैरामीटर में पास करने के लिए *args और **kwargs का उपयोग कर सकते हैं।

पैरामीटर प्राप्त करने वाले फ़ंक्शन को यह नहीं पता होना चाहिए कि उनका विस्तार किया जा रहा है।

उदाहरण के लिए, पायथन 2 का xrange स्पष्ट रूप से *args तर्क की अपेक्षा नहीं करता है, लेकिन चूंकि यह 3 पूर्णांक को तर्क के रूप में लेता है:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

एक और उदाहरण के रूप में, हम str.format में dict विस्तार का उपयोग कर सकते हैं:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

पायथन 3 में नया: केवल तर्क के साथ कार्यों को परिभाषित करना

आपके पास *args तर्कों के बाद केवल तर्क ही हो सकते हैं - उदाहरण के लिए, यहां, kwarg2 को कीवर्ड तर्क के रूप में दिया जाना चाहिए - kwarg2 रूप से नहीं:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

उपयोग:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

इसके अलावा, * असीमित स्थितित्मक तर्कों की अनुमति के बिना, कीवर्ड केवल तर्कों का पालन करने के लिए स्वयं ही इसका उपयोग किया जा सकता है।

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

यहां, kwarg2 फिर से एक स्पष्ट नाम, कीवर्ड तर्क होना चाहिए:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

और अब हम असीमित स्थितित्मक तर्क स्वीकार नहीं कर सकते क्योंकि हमारे पास *args* नहीं है:

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

फिर, अधिक सरलता से, यहां हमें नाम से दिए जाने वाले kwarg आवश्यकता है, न कि स्थिति में:

def bar(*, kwarg=None): 
    return kwarg

इस उदाहरण में, हम देखते हैं कि अगर हम स्थिति में kwarg पास करने का प्रयास करते हैं, तो हमें एक त्रुटि मिलती है:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

हमें स्पष्ट रूप से कीवर्ड तर्क के रूप में kwarg पैरामीटर को पारित करना होगा।

>>> bar(kwarg='kwarg')
'kwarg'

पायथन 2 संगत डेमो

*args (आमतौर पर "स्टार-Args" कहा जाता है) और **kwargs (सितारों को "kwargs" कहकर निहित किया जा सकता है, लेकिन "डबल-स्टार kwargs" के साथ स्पष्ट होना चाहिए) * और ** नोटेशन का उपयोग करने के लिए पाइथन के सामान्य मुहावरे हैं । इन विशिष्ट परिवर्तनीय नामों की आवश्यकता नहीं है (उदाहरण के लिए आप *foos और **bars उपयोग कर सकते हैं), लेकिन सम्मेलन से प्रस्थान आपके साथी पायथन कोडर्स को क्रोधित करने की संभावना है।

हम आम तौर पर इनका उपयोग करते हैं जब हम नहीं जानते कि हमारा कार्य क्या प्राप्त करने जा रहा है या हम कितने तर्क पारित कर रहे हैं, और कभी-कभी प्रत्येक चर को अलग-अलग नाम देने पर भी बहुत गन्दा और अनावश्यक होता है (लेकिन यह एक ऐसा मामला है जहां आमतौर पर स्पष्ट होता है निहित से बेहतर)।

उदाहरण 1

निम्नलिखित कार्य वर्णन करता है कि उनका उपयोग कैसे किया जा सकता है, और व्यवहार का प्रदर्शन करता है। ध्यान दें कि नामित b तर्क पहले दूसरे स्थितित्मक तर्क से उपभोग किया जाएगा:

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

हम फंक्शन के हस्ताक्षर के लिए help(foo) साथ ऑनलाइन सहायता देख सकते हैं, जो हमें बताता है

foo(a, b=10, *args, **kwargs)

आइए इस फ़ंक्शन को foo(1, 2, 3, 4, e=5, f=6, g=7) साथ कॉल करें

जो प्रिंट करता है:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

उदाहरण 2

हम इसे किसी अन्य फ़ंक्शन का उपयोग करके भी कॉल कर सकते हैं, जिसमें हम केवल a प्रदान करते हैं:

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) प्रिंट:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

उदाहरण 3: सजावटी में व्यावहारिक उपयोग

ठीक है, तो शायद हम अभी तक उपयोगिता नहीं देख रहे हैं। तो कल्पना करें कि आपके पास पहले और / या अलग-अलग कोड के बाद अनावश्यक कोड के साथ कई फ़ंक्शन हैं। निम्नलिखित नामित फ़ंक्शंस चित्रकारी उद्देश्यों के लिए केवल छद्म कोड हैं।

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

हम इसे अलग-अलग संभालने में सक्षम हो सकते हैं, लेकिन हम निश्चित रूप से एक सजावटी के साथ अनावश्यकता निकाल सकते हैं, और इसलिए हमारा नीचे उदाहरण दिखाता है कि कैसे *args और **kwargs बहुत उपयोगी हो सकते हैं:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

और अब हर लपेटा हुआ कार्य अधिक संक्षेप में लिखा जा सकता है, क्योंकि हमने अनावश्यकता को ठीक किया है:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

और हमारे कोड को *args करके, जो *args और **kwargs हमें करने की अनुमति देता है, हम कोड की रेखाओं को कम करते हैं, पठनीयता और रखरखाव में सुधार करते हैं, और हमारे कार्यक्रम में तर्क के लिए एकमात्र कैननिक स्थान हैं। अगर हमें इस संरचना के किसी भी हिस्से को बदलने की जरूरत है, तो हमारे पास एक ही स्थान है जिसमें प्रत्येक परिवर्तन करना है।

निम्नलिखित विधि परिभाषाओं में, * और ** param2 लिए क्या करता है?

def foo(param1, *param2):
def bar(param1, **param2):

* args = * aist = सूची में सभी तत्व

** args = ** aDict = एक आइटम में सभी आइटम


पायथन 3.5 में, आप list , dict , tuple , और set डिस्प्ले (कभी-कभी शाब्दिक भी कहा जाता है) में इस वाक्यविन्यास का उपयोग कर सकते हैं। पीईपी 488 देखें : अतिरिक्त अनपॅकिंग सामान्यीकरण

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

यह एक एकल फ़ंक्शन कॉल में एकाधिक पुनरावृत्तियों को अनपॅक करने की अनुमति भी देता है।

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(पीईपी लिंक के लिए mgilson के लिए धन्यवाद।)


पायथन दस्तावेज से:

यदि औपचारिक पैरामीटर स्लॉट्स की तुलना में अधिक स्थितित्मक तर्क हैं, तो टाइपएरर अपवाद उठाया जाता है, जब तक कि वाक्यविन्यास "* पहचानकर्ता" का उपयोग करने वाला औपचारिक पैरामीटर मौजूद न हो; इस मामले में, उस औपचारिक पैरामीटर को एक अतिरिक्त ट्यूपल प्राप्त होता है जिसमें अतिरिक्त स्थितित्मक तर्क होते हैं (या यदि कोई अतिरिक्त स्थितित्मक तर्क नहीं होते हैं तो खाली टुपल)।

यदि कोई कीवर्ड तर्क औपचारिक पैरामीटर नाम से मेल नहीं खाता है, तो टाइपएरर अपवाद उठाया जाता है, जब तक कि वाक्यविन्यास "** पहचानकर्ता" का उपयोग करने वाला औपचारिक पैरामीटर मौजूद न हो; इस मामले में, उस औपचारिक पैरामीटर में एक अतिरिक्त शब्द तर्क (कीवर्ड के रूप में कुंजी और तर्क मानों को संबंधित मानों के रूप में उपयोग करना), या एक (नया) खाली शब्दकोश होता है जिसमें कोई अतिरिक्त कीवर्ड तर्क नहीं होता है।


फ़ंक्शन में दोनों का उपयोग करने का एक अच्छा उदाहरण है:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

मैं एक उदाहरण देना चाहता हूं जिसे दूसरों ने उल्लेख नहीं किया है

* जनरेटर को अनपैक भी कर सकता है

पायथन 3 दस्तावेज़ से एक उदाहरण

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x होगा [1, 2, 3], unzip_y होगा [4, 5, 6]

ज़िप () को एकाधिक iretable तर्क प्राप्त होता है, और जनरेटर लौटाता है।

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

यह ध्यान देने योग्य भी है कि आप कार्यों को कॉल करते समय * और ** उपयोग भी कर सकते हैं। यह एक शॉर्टकट है जो आपको किसी सूची / टुपल या शब्दकोश का उपयोग करके फ़ंक्शन में एकाधिक तर्क पारित करने की अनुमति देता है। उदाहरण के लिए, यदि आपके पास निम्न कार्य है:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

आप चीजें कर सकते हैं जैसे:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

नोट: mydict में mydict को फ़ंक्शन foo के पैरामीटर की तरह बिल्कुल नामित किया जाना चाहिए। अन्यथा यह एक TypeError फेंक देगा:

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

सिंगल * का मतलब है कि अतिरिक्त स्थितित्मक तर्कों की संख्या हो सकती है। foo() को foo(1,2,3,4,5) जैसे बुलाया जा सकता है। Foo () param2 के शरीर में एक अनुक्रम 2-5 होता है।

डबल ** का मतलब है कि अतिरिक्त नामित पैरामीटर की संख्या हो सकती है। bar() bar(1, a=2, b=3) जैसे आह्वान किया जा सकता है। बार के शरीर में () param2 एक शब्दकोश है जिसमें '' a ': 2,' b ': 3} है

निम्नलिखित कोड के साथ:

def foo(param1, *param2):
    print param1
    print param2

def bar(param1, **param2):
    print param1
    print param2

foo(1,2,3,4,5)
bar(1,a=2,b=3)

आउटपुट है

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

* और ** फ़ंक्शन तर्क सूची में विशेष उपयोग है। * तात्पर्य है कि तर्क एक सूची है और ** का तात्पर्य है कि तर्क एक शब्दकोश है। यह कार्यों को मनमाने ढंग से तर्कों की संख्या लेने की अनुमति देता है


*args तर्क और **kwargs एक सामान्य मुहावरे है जो कि पाइथन दस्तावेज़ में कार्यों को परिभाषित करने के लिए अनुभाग में वर्णित कार्यों के मनमाने ढंग से तर्कों की अनुमति देता है।

*args आपको सभी फ़ंक्शन पैरामीटर को टुपल के रूप में देगा :

In [1]: def foo(*args):
   ...:     for a in args:
   ...:         print a
   ...:         
   ...:         

In [2]: foo(1)
1


In [4]: foo(1,2,3)
1
2
3

**kwargs आपको एक शब्दकोश के रूप में औपचारिक पैरामीटर से संबंधित सभी को छोड़कर सभी कीवर्ड तर्क देगा।

In [5]: def bar(**kwargs):
   ...:     for a in kwargs:
   ...:         print a, kwargs[a]
   ...:         
   ...:         

In [6]: bar(name='one', age=27)
age 27
name one

निश्चित और कुछ परिवर्तनीय तर्कों के सेट को अनुमति देने के लिए दोनों मुहावरों को सामान्य तर्कों के साथ मिश्रित किया जा सकता है:

def foo(kind, *args, **kwargs):
   pass

*l idiom का एक और उपयोग फ़ंक्शन को कॉल करते समय तर्क सूचियों को अनपैक करना है।

In [9]: def foo(bar, lee):
   ...:     print bar, lee
   ...:     
   ...:     

In [10]: l = [1,2]

In [11]: foo(*l)
1 2

पायथन 3 में असाइनमेंट के बाईं ओर *l का उपयोग करना संभव है ( विस्तारित इटेरबल अनपॅकिंग ), हालांकि यह इस संदर्भ में एक टुपल की बजाय एक सूची देता है:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

इसके अलावा पायथन 3 नए अर्थपूर्ण जोड़ता है ( पीईपी 3102 देखें):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

इस तरह का कार्य केवल 3 स्थितित्मक तर्क स्वीकार करता है, और सब कुछ * बाद केवल कीवर्ड तर्क के रूप में पारित किया जा सकता है।





kwargs