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