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


2347

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

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



यह भी देखें stackoverflow.com/questions/14301967/… एक नंगे
तार के लिए

23
यह प्रश्न एक बहुत लोकप्रिय डुप्लिकेट लक्ष्य है, लेकिन दुर्भाग्य से इसका उपयोग अक्सर गलत तरीके से किया जाता है। ध्यान रखें कि यह सवाल वार्गर्स ( def func(*args)) के साथ फ़ंक्शंस को परिभाषित करने के बारे में पूछता है । फ़ंक्शन कॉल ( func(*[1,2])) में इसका क्या अर्थ है, यह पूछने के लिए यहां देखें । एक सवाल पूछने के लिए कि तर्क सूचियों को कैसे अनपैक करें, यहां देखें । एक प्रश्न के लिए कि शाब्दिक* अर्थ क्या है ( [*[1, 2]]) यहाँ देखें ।
अरण-फे

आप फ़ंक्शन परिभाषा और फ़ंक्शन कॉल में इसके उपयोग के बारे में जान सकते हैं: pythontips.com/2013/08/04/args-and-kwargs-in-python-explained
अक्षय अनुराग

जवाबों:


2234

*argsऔर **kwargsएक आम मुहावरा कार्यों खंड में वर्णित के रूप में करने के लिए तर्क का मनमाना संख्या अनुमति है कार्यों को परिभाषित करने के बारे में अधिक अजगर दस्तावेज में।

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

def foo(*args):
    for a in args:
        print(a)        

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

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

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

bar(name='one', age=27)
# age 27
# name one

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

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

इसे अन्य तरीके से उपयोग करना भी संभव है:

def foo(a, b, c):
    print(a, b, c)

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

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

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

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

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

इसके अलावा पायथन 3 में नया शब्दार्थ ( पीईपी 3102 देखें ):

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

ऐसे फ़ंक्शन केवल 3 स्थितिगत तर्क स्वीकार करते हैं, और उसके बाद सब कुछ *केवल कीवर्ड तर्क के रूप में पारित किया जा सकता है।


9
[६] का आउटपुट रिवर्स ऑर्डर में है। नाम एक उम्र 27
thanos.a

53
@ thanos.a Python dicts, शब्दार्थ पासिंग के लिए शब्दार्थ रूप से प्रयुक्त, मनमाने ढंग से क्रमबद्ध हैं। हालांकि, पायथन 3.6 में, सम्मिलन आदेश को याद रखने के लिए कीवर्ड तर्क की गारंटी है। " **kwargsअब तत्वों का क्रम उस क्रम से मेल खाता है जिसमें कीवर्ड तर्क फ़ंक्शन में पारित किए गए थे।" - docs.python.org/3/whatsnew/3.6.html वास्तव में, CPython 3.6 में सभी dicts कार्यान्वयन विवरण के रूप में प्रविष्टि क्रम को याद रखेंगे, यह पायथन 3.7 में मानक बन जाता है।
हारून हॉल

13
बहुत सटीक, साफ, और समझने में आसान। मैं सराहना करता हूं कि आपने नोट किया कि यह एक "अनपैकिंग ऑपरेटर" है, ताकि मैं सी। +1 में संदर्भ से गुजरने में अंतर कर
सकूं

PEP 3102 के साथ अंतिम फ़ंक्शन का परीक्षण कैसे करें? मैं इसे फंक (1,2,3, नाम = "मुझे", उम्र = 10) के साथ कहता हूं और यह अपवाद को फेंक देता है:got an unexpected keyword argument 'name'
कोक हाउ ते

@KokHowTeh आपको फंक्शन में आने वाले नाम के कंवरों को पास करना होगा: func (1, 2, 3, kwarg1 = 'me', kwarg2 = 10)
John Aaron

622

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

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को फ़ंक्शन के मापदंडों की तरह ही नाम दिया जाना चाहिए 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'

175

एकल * का मतलब है कि किसी भी अतिरिक्त स्थिति संबंधी तर्क हो सकते हैं। foo()की तरह लगाया जा सकता है foo(1,2,3,4,5)। फू के शरीर में () परम 2 एक क्रम है जिसमें 2-5 होते हैं।

डबल ** का मतलब है कि अतिरिक्त नामित मापदंडों की कोई संख्या हो सकती है। bar()की तरह लगाया जा सकता है bar(1, a=2, b=3)। बार के शरीर में () परम 2 एक शब्दकोश है जिसमें {'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}

4
शायद foobar(param1, *param2, **param3)इस उत्तर की पूर्णता के लिए एक अतिरिक्त उदाहरण की आवश्यकता है।
अनिकेत ठाकुर

1
@AniketThakur ने यहां शेष भाग जोड़ा ।
राज

147

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

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

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

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

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

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

विस्तार, किसी भी तर्क को पारित करना

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

मापदंडों पर भरोसा करने वाले फ़ंक्शन को यह जानने की ज़रूरत नहीं है कि उनका विस्तार किया जा रहा है।

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

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

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

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

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

आपके पास खोजशब्द तर्क हो सकते हैं *args- उदाहरण के लिए, यहाँ, 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(आमतौर पर "स्टार-आर्ग्स" कहा जाता है) और **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और **kwargsहमें करने की अनुमति देता है, हम कोड की लाइनों को कम करने, पठनीयता और रख-रखाव में सुधार, और हमारे कार्यक्रम में तर्क के लिए एकमात्र विहित स्थान नहीं हैं। यदि हमें इस संरचना के किसी भी हिस्से को बदलने की आवश्यकता है, तो हमारे पास एक स्थान है जिसमें प्रत्येक परिवर्तन करना है।


48

आइए पहले समझते हैं कि स्थितिगत तर्क और खोजशब्द तर्क क्या हैं। नीचे स्थितीय तर्कों के साथ फ़ंक्शन परिभाषा का एक उदाहरण है

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

तो यह एक फ़ंक्शन परिभाषा है जिसमें स्थिति संबंधी तर्क हैं। आप इसे कीवर्ड / नामित तर्कों के साथ भी कॉल कर सकते हैं:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

अब हम कीवर्ड तर्कों के साथ फ़ंक्शन परिभाषा का एक उदाहरण पढ़ते हैं :

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

आप इस फ़ंक्शन को स्थिति संबंधी तर्कों के साथ भी कॉल कर सकते हैं:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

इसलिए अब हम स्थितीय और खोजशब्द तर्कों के साथ कार्य परिभाषाएँ जानते हैं।

अब '' '' ऑपरेटर और '**' ऑपरेटर का अध्ययन करते हैं।

कृपया ध्यान दें कि ये ऑपरेटर 2 क्षेत्रों में उपयोग किए जा सकते हैं:

ए) फ़ंक्शन कॉल

बी) फ़ंक्शन परिभाषा

फ़ंक्शन कॉल में '*' ऑपरेटर और '**' ऑपरेटर का उपयोग।

आइए हम एक उदाहरण पर सीधे आते हैं और फिर इस पर चर्चा करते हैं।

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

इसलिए याद रखें

जब फ़ंक्शन कॉल में '*' या '**' ऑपरेटर का उपयोग किया जाता है -

'*' ऑपरेटर फंक्शन डेफिनेशन द्वारा आवश्यक तर्कों में डेटा संरचना जैसे कि लिस्ट या ट्यूपल को अनपैक करता है।

'**' ऑपरेटर फ़ंक्शन परिभाषा के लिए आवश्यक तर्कों में एक शब्दकोश को खोल देता है।

अब ' फंक्शन डेफिनिशन ' में ऑपरेटर 'यूज' का इस्तेमाल करते हैं । उदाहरण:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

समारोह में परिभाषा में '*' ऑपरेटर प्राप्त तर्कों को टपल में पैक करता है।

अब हम '**' का एक उदाहरण देखते हैं जिसका उपयोग फ़ंक्शन परिभाषा में किया जाता है:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

समारोह में परिभाषा में '**' ऑपरेटर प्राप्त तर्कों को एक शब्दकोश में पैक करता है।

तो याद रखें:

किसी फ़ंक्शन में '*' कॉल करें टपल के डेटा स्ट्रक्चर को अनपैक करते हैं या फंक्शन डेफिनिशन द्वारा प्राप्त करने के लिए पॉज़िटिव या कीवर्ड तर्क में सूची बनाते हैं।

एक फ़ंक्शन में '**' अनपैक को कॉल करता है में डिक्शनरी में शब्दकोश की डेटा संरचना को या कीवर्ड तर्कों में फ़ंक्शन परिभाषा द्वारा प्राप्त करने के लिए ।

एक फ़ंक्शन में '*' पैक की परिभाषा है स्थिति तर्क को एक तुक में ।

एक फ़ंक्शन में '**' शब्दकोष के तर्क को डिक्शनरी में पैक करता है।


वास्तव में स्वच्छ, चरण-दर-चरण और स्पष्टीकरण का पालन करना आसान है!
अलेक्जेंडर

धन्यवाद आने वाले चढ़ाव को बनाए रखें। [इसके अलावा मुझसे और नोट्स के लिए, मैं ट्विटर पर @mrtechmaker पर हूं]
करण आहूजा

32

यह तालिका उपयोग करने के लिए *और **फ़ंक्शन निर्माण और फ़ंक्शन कॉल में आसान है :

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

यह वास्तव में लोरिन होचस्टीन के जवाब को संक्षेप में प्रस्तुत करने का काम करता है, लेकिन मुझे यह मददगार लगता है।

संबंधित: स्टार / स्पैट ऑपरेटरों के लिए उपयोग पायथन 3 में विस्तारित किए गए हैं


22

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


17

आप में से जो उदाहरणों से सीखते हैं!

  1. इसका उद्देश्य * आपको एक फ़ंक्शन को परिभाषित करने की क्षमता प्रदान करना है जो एक सूची के रूप में प्रदान की गई मनमानी संख्या ले सकता है (जैसेf(*myList) ) के ।
  2. इसका उद्देश्य **आपको एक शब्दकोश (उदाहरण f(**{'x' : 1, 'y' : 2})) प्रदान करके एक फ़ंक्शन के तर्कों को खिलाने की क्षमता प्रदान करना है ।

हमें इस दिखाती हूँ एक समारोह है कि दो सामान्य चर लेता है परिभाषित करते हुए x, yऔर के रूप में अधिक तर्क स्वीकार कर सकते हैं myArgs, और जैसा कि और भी अधिक तर्क स्वीकार कर सकते हैं myKW। बाद में, हम दिखाएंगे कि कैसे yउपयोग करके फ़ीड करना है myArgDict

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

चेतावनियां

  1. ** विशेष रूप से शब्दकोशों के लिए आरक्षित है।
  2. गैर-वैकल्पिक तर्क असाइनमेंट पहले होता है।
  3. आप दो बार गैर-वैकल्पिक तर्क का उपयोग नहीं कर सकते।
  4. यदि लागू **हो *, तो हमेशा के बाद आना चाहिए ।

14

पायथन प्रलेखन से:

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

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


10

* इसका मतलब है कि टुपल के रूप में चर तर्क प्राप्त करें

** शब्दकोश के रूप में चर तर्क प्राप्त करते हैं

निम्नलिखित की तरह इस्तेमाल किया:

1) एकल *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

आउटपुट:

two
3

2) अब **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

आउटपुट:

dic1 two
dic2 3

8

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

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

पायथन 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 args प्राप्त करता है, और एक जनरेटर वापस।

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

7

अजगर 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)

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


1
मुझे यकीन नहीं है कि यह "ऐसा करने का केवल एक तरीका है" का उल्लंघन है। कई पुनरावृत्तियों से किसी सूची / टपल को इनिशियलाइज़ करने का कोई अन्य तरीका नहीं है - आपको वर्तमान में उन्हें एक एकल पुनरावृत्ति में श्रृंखलाबद्ध करने की आवश्यकता है जो हमेशा सुविधाजनक नहीं होता है। आप PEP-0448 में तर्कसंगत के बारे में पढ़ सकते हैं । इसके अलावा, यह एक python3.x सुविधा नहीं है, यह python3.5 + सुविधा :-) है।
एमजीसिलसन

@mgilson, यह बताएगा कि इसका उल्लेख पहले क्यों नहीं किया गया था।
लेवेज़

6

फंक्शन कॉल्स के अलावा, * आर्ग्स और ** क्वार्ग्स क्लास पदानुक्रम में उपयोगी होते हैं और __init__पायथन में विधि लिखने से भी बचते हैं । इसी तरह का उपयोग Django कोड जैसे फ्रेमवर्क में देखा जा सकता है।

उदाहरण के लिए,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

एक उपवर्ग तो हो सकता है

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

उपवर्ग को तत्क्षण बदल दिया जाएगा

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

इसके अलावा, एक नई विशेषता के साथ एक उपवर्ग जो केवल उस उपवर्ग उदाहरण के लिए समझ में आता है वह बेस क्लास __init__को कॉल कर सकता है ताकि विशेषता सेटिंग को ऑफलोड किया जा सके। यह * args और ** kwargs के माध्यम से किया जाता है। kwargs मुख्य रूप से उपयोग किया जाता है ताकि कोड नाम तर्क का उपयोग कर पठनीय हो। उदाहरण के लिए,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

जिसे उकसाया जा सकता है

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

पूरा कोड यहाँ है


1
1. मूल रूप से init एक विधि है, तो (इस प्रसंग में) यह वास्तव में अलग नहीं है। 2. "टिप्पणियों के लिए" का प्रयोग करें, "" "नहीं, जो सिर्फ शाब्दिक तार को चिह्नित करता है। 3. सुपर का उपयोग पसंदीदा तरीका होना चाहिए, विशेष रूप से आपके उदाहरण के लिए बहु-स्तरीय विरासत के साथ।
0xc0de

4

निक के जवाब पर बिल्डिंग ...

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


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


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

आउटपुट:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

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

मूल रूप से, किसी भी स्थिति संबंधी तर्कों का उपयोग * आर्ग और किसी भी नामित तर्क (या kwargs उर्फ ​​कीवर्ड तर्क) ** kwargs का उपयोग कर सकते हैं।


3

*argsऔर **kwargs: आप किसी फ़ंक्शन के लिए चर संख्याओं को पास करने की अनुमति देते हैं।

*args: फंक्शन में एक नॉन-कीवर्डेड वैरिएबल लेंथ लिस्ट लिस्ट भेजने के लिए उपयोग किया जाता है:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

उत्पादन करेंगे:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargsआपको किसी फ़ंक्शन के लिए कीवर्ड की परिवर्तनीय लंबाई पास करने की अनुमति देता है। **kwargsयदि आप किसी फ़ंक्शन में नामित तर्कों को संभालना चाहते हैं, तो आपको इसका उपयोग करना चाहिए ।

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

उत्पादन करेंगे:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.

2

यह उदाहरण आपको याद रखने में मदद करेगा *args, **kwargsऔर यहां तक ​​कि superएक बार में पायथन में विरासत भी ।

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

1

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

>>> 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')
{}

1

टी एल; डॉ

नीचे *और **अजगर प्रोग्रामिंग में 6 अलग-अलग उपयोग के मामले हैं :

  1. किसी भी स्थिति संबंधी तर्कों का उपयोग करने के लिए *args:, def foo(*args): pass यहाँ fooकिसी भी स्थैतिक तर्क को स्वीकार किया जाता है, अर्थात, निम्नलिखित कॉल मान्य हैं foo(1),foo(1, 'bar')
  2. किसी भी संख्या के तर्क का उपयोग करके स्वीकार करने के लिए **kwargs: def foo(**kwargs): pass यहाँ, 'foo' किसी भी संख्या के खोजशब्द तर्क को स्वीकार करता है, अर्थात, निम्नलिखित विकल्प मौजूद हैं foo(name='Tom'),foo(name='Tom', age=33)
  3. किसी भी संख्या में स्थितीय और खोजशब्द तर्क का उपयोग करने के लिए *args, **kwargs:, def foo(*args, **kwargs): pass यहाँ fooकिसी भी संख्या में स्थितीय और खोजशब्द तर्क स्वीकार करते हैं, अर्थात, निम्नलिखित कॉल मान्य हैं foo(1,name='Tom')foo(1, 'bar', name='Tom', age=33)
  4. कीवर्ड का उपयोग करने के लिए केवल तर्कों को लागू करने के लिए *: def foo(pos1, pos2, *, kwarg1): pass यहां *इसका मतलब है कि foo केवल pos2 के बाद कीवर्ड तर्क को स्वीकार करते हैं, इसलिए टाइप-इयरर को foo(1, 2, 3)उठाता है , लेकिन foo(1, 2, kwarg1=3)ठीक है।
  5. अधिक स्थितिगत तर्कों का उपयोग करने में कोई दिलचस्पी नहीं व्यक्त करने के लिए *_(ध्यान दें: यह केवल एक सम्मेलन है): def foo(bar, baz, *_): pass इसका मतलब है (सम्मेलन द्वारा) fooकेवल barऔर केवल उपयोगbaz अपने काम में तर्क देता है और दूसरों की उपेक्षा करेगा।
  6. का उपयोग कर अधिक कीवर्ड तर्कों में कोई और रुचि नहीं व्यक्त करने के लिए \**_(नोट: यह केवल एक सम्मेलन है): def foo(bar, baz, **_): pass इसका मतलब है (सम्मेलन द्वारा) fooकेवल अपने काम में उपयोग करता है barऔर bazतर्क देता है और दूसरों की उपेक्षा करेगा।

बोनस: पायथन 3.8 से आगे की ओर, कोई भी /कार्य केवल मानदंड को लागू करने के लिए फ़ंक्शन परिभाषा में उपयोग कर सकता है । निम्नलिखित उदाहरण में, पैरामीटर a और b स्थिति-मात्र हैं , जबकि c या d स्थिति-संबंधी या कीवर्ड हो सकते हैं, और कीवर्ड होने के लिए e या f आवश्यक हैं:

def f(a, b, /, c, d, *, e, f):
    pass

0

टी एल; डॉ

यह फ़ंक्शन बॉडी के अंदर listऔर dictक्रमशः फ़ंक्शन को दिए गए तर्कों को पैक करता है। जब आप एक फ़ंक्शन हस्ताक्षर को इस तरह परिभाषित करते हैं:

def func(*args, **kwds):
    # do stuff

इसे किसी भी तर्क और कीवर्ड तर्क के साथ बुलाया जा सकता है। गैर-कीवर्ड तर्क argsफ़ंक्शन बॉडी के अंदर नामक एक सूची में पैक हो जाते हैं और कीवर्ड तर्क kwdsफ़ंक्शन बॉडी के अंदर एक तानाशाह में पैक हो जाते हैं।

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

अब फंक्शन बॉडी के अंदर, जब फंक्शन को कॉल किया जाता है, तो दो लोकल वैरिएबल होते हैं, argsजो एक लिस्ट होता है जिसकी वैल्यू होती है ["this", "is a list of", "non-keyword", "arguments"]और kwdsजो एक dictवैल्यू होता है{"keyword" : "ligma", "options" : [1,2,3]}


यह रिवर्स में भी काम करता है, यानी कॉलर की तरफ से। उदाहरण के लिए यदि आपके पास कोई फ़ंक्शन है जिसे इस प्रकार परिभाषित किया गया है:

def f(a, b, c, d=1, e=10):
    # do stuff

आप इसे कॉलिंग स्कोप में पुनरावृत्तियों या मैपिंग के साथ कॉल कर सकते हैं:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

0

प्रसंग

  • अजगर 3.x
  • साथ उतारना **
  • स्ट्रिंग स्वरूपण के साथ उपयोग करें

स्ट्रिंग प्रारूपण के साथ प्रयोग करें

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

**अजगर का उपयोग करते समय इसके साथ अनपैक करना भी उपयोगी होता है str.format

यह कुछ हद तक आप अजगर एफ-स्ट्रिंग के साथ क्या कर सकते हैं के समान हैf-strings लेकिन चर को पकड़ने के लिए एक तानाशाह घोषित करने के अतिरिक्त ओवरहेड के साथ (एफ-स्ट्रिंग को एक तानाशाह की आवश्यकता नहीं है)।

त्वरित उदाहरण

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])

-2
  • def foo(param1, *param2):एक विधि है *param2, जिसके लिए मानों की संख्या को मनमाना स्वीकार कर सकते हैं ,
  • def bar(param1, **param2): एक विधि है जिसके लिए कुंजी के साथ मानों की मनमानी संख्या को स्वीकार कर सकते हैं *param2
  • param1 एक साधारण पैरामीटर है।

उदाहरण के लिए, जावा में varargs को लागू करने के लिए सिंटैक्स निम्नानुसार है:

accessModifier methodName(datatype arg) {
    // method body
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.