फंक्शन कॉल में स्टार ऑपरेटर का क्या मतलब है?


630

*पायथन में ऑपरेटर का क्या मतलब है, जैसे कोड में zip(*x)या f(**k)?

  1. यह दुभाषिया में आंतरिक रूप से कैसे संभाला जाता है?
  2. क्या यह प्रदर्शन को प्रभावित करता है? क्या यह तेज या धीमा है?
  3. यह कब उपयोगी है और कब नहीं?
  4. क्या इसे फ़ंक्शन डिक्लेरेशन में या कॉल में उपयोग किया जाना चाहिए?

परिशिष्ट: stackoverflow.com/questions/1141504/...
WDS

4
मुझे लगता है कि इसे "* फ़ंक्शन कॉल सिंटैक्स" के रूप में संक्षिप्त किया जाना चाहिए। वे के रूप में वहाँ है, हालांकि यह भ्रमित हो जाएगी, ऑपरेटरों नहीं कर रहे हैं है एक *और **ऑपरेटर इस वाक्य के साथ कुछ नहीं किया है।
इयान बेकिंग

1
@ इयान बेकिंग: आप पूर्ण अधिकार हैं, * और ** तर्क सूची में शुद्ध वाक्यविन्यास (टोकन) हैं।
पी। ओर्टिज़

2
ध्यान दें: PEP 448 के लिए: अतिरिक्त अनपैकिंग सामान्यीकरण विशिष्ट सामान (जैसे [*a, b, *c]या {**d1, **d2}), आप टपल, सूची और सेट परिभाषाओं में तारांकन को पढ़ना चाहते हैं , तानाशाही परिभाषा में डबल तारांकन , जो फ़ंक्शन कॉल और फ़ंक्शन परिभाषाओं के बाहर उपयोग के लिए विशिष्ट है। । पहले के PEP 3132 के लिए , जब आप अनुक्रम लंबाई नहीं जानते, तो कई अनपैकिंग पायथन में देखें ।
शैडो रेंजर

1
वीटीआर - यह मापदंडों के लिए क्या करता है ** (डबल स्टार / तारांकन) और * (स्टार / तारांकन) का डुप्लिकेट नहीं है ? चूँकि यह प्रश्न केवल मापदंडों के बारे में है, भले ही उत्तर फ़ंक्शन कॉल को भी कवर करते हैं। फंक्शन कॉल में तारांकन चिह्न को इस प्रश्न के डुप्लिकेट के रूप में चिह्नित किया जाना चाहिए क्योंकि यह कम लोकप्रिय है और शीर्ष उत्तर कम पूर्ण है।
वजंड्रिया

जवाबों:


966

सिंगल स्टार *सीक्वेंस / कलेक्शन को पॉजिटिव आर्ग्युमेंट्स में अनपैक करता है, इसलिए आप ऐसा कर सकते हैं:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

यह टपल को अनपैक करेगा ताकि वह वास्तव में इस प्रकार निष्पादित हो:

s = sum(1, 2)

डबल स्टार **एक ही करता है, केवल एक शब्दकोश का उपयोग करता है और इस प्रकार नाम तर्क देता है:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

आप भी जोड़ सकते हैं:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

के रूप में निष्पादित करेगा:

s = sum(1, 2, c=10, d=15)

इसके अलावा खंड ४.२.४ देखें - पायथन प्रलेखन की अनप्लगिंग सूची


इसके अतिरिक्त, आप कार्यों को लेने *xऔर **yबहस करने के लिए परिभाषित कर सकते हैं , यह फ़ंक्शन को किसी भी स्थिति और / या नामित तर्कों को स्वीकार करने की अनुमति देता है जो विशेष रूप से घोषणा में नामित नहीं हैं।

उदाहरण:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

या साथ **:

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

यह आपको उन्हें घोषित किए बिना बड़ी संख्या में वैकल्पिक मापदंडों को निर्दिष्ट करने की अनुमति दे सकता है।

और फिर से, आप गठबंधन कर सकते हैं:

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15

4
आपको इसकी आवश्यकता क्यों होगी, यह बिना विस्तारित किए आपूर्ति की गई सूची पर कार्य को पूरा नहीं कर सकता है?
मार्टिन बेकेट

30
ज़रूर, लेकिन फिर आपको इसे कॉल करना होगा: s = sum((1, 2, 3, 4, 5))या s = sum([1, 2, 3, 4, 5]), *valuesविकल्प कॉल को ऐसा दिखता है जैसे कि यह कई तर्क लेता है, लेकिन वे फ़ंक्शन कोड के लिए एक संग्रह में पैक किए जाते हैं।
लास वी। कार्लसन

12
यहां वास्तविक लाभ है: आप उन कार्यों को लिख सकते हैं जो अन्यथा संभव नहीं होंगे यदि आपको चर संख्या में तर्क की आवश्यकता हो। उदाहरण के लिए, C का प्रिंटफ फ़ंक्शन, जिसमें 1 + n तर्क हैं, किसी भी शुरुआती प्रोग्रामर के लिए एक अभ्यास के रूप में लिखने के लिए मुश्किल है। पायथन में, एक शुरुआती डीफ प्रिंटफ (string_template, * args) लिख सकता है और आगे बढ़ सकता है।
IceArdor

1
यदि आप (गलती से शायद: पी) दो के बजाय केवल एक * के साथ एक शब्दकोश अनपैक करते हैं तो क्या होता है? यह कुछ करने के लिए लगता है, ऐसा लगता है जैसे एक टपल बाहर आता है, लेकिन यह इतना स्पष्ट नहीं है कि यह क्या है। (संपादित करें: ठीक है, मुझे लगता है कि इसका उत्तर यह है कि यह सिर्फ चाबियों को खोल देता है, मानों को छोड़ दिया जाता है)
बेन किसान

1
अंतिम उदाहरण का तात्पर्य यह है कि * और ** न केवल अनपैकिंग कर रहे हैं बल्कि पैकिंग भी कर रहे हैं! इस उत्कृष्ट पृष्ठ देखें codingame.com/playgrounds/500/...
HCChen

46

एक छोटा बिंदु: ये ऑपरेटर नहीं हैं। ऑपरेटर्स का उपयोग मौजूदा मानों से नए मान बनाने के लिए अभिव्यक्तियों में किया जाता है (उदाहरण के लिए 1 + 2 3 हो जाता है। * * और ** यहां फ़ंक्शन डिक्लेरेशन और कॉल के सिंटैक्स का हिस्सा हैं।


7
ध्यान दें कि पायथन डॉक्यूमेंटेशन इस संदर्भ में * ऑपरेटर कहता है; मैं मानता हूं, यह भ्रामक है।
क्रिस्टोफ

धन्यवाद। मैं अजगर संदर्भ प्रलेखन में इस के एक स्पष्ट प्रदर्शनी के लिए देख रहा हूँ और अभी भी इसे नहीं देखते हैं। इसलिए फ़ंक्शन कॉल के लिए नियम मूल रूप से एक "*" या "**" है जो एक फ़ंक्शन कॉल के भीतर एक अभिव्यक्ति की शुरुआत में है इस तरह के विस्तार का कारण बनता है?
nealmcb

21

जब आप फ़ंक्शन कॉल करना चाहते हैं तो मुझे यह विशेष रूप से उपयोगी लगता है।

उदाहरण के लिए, मान लीजिए कि एक फंक्शन 'ऐड' के लिए मेरे पास कुछ यूनिट टेस्ट हैं:

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

ऐड को कॉल करने का कोई अन्य तरीका नहीं है, मैन्युअल रूप से ऐड (टेस्ट [0], टेस्ट [1]) जैसे कुछ करने के अलावा, जो बदसूरत है। इसके अलावा, यदि कोई चर संख्या होती है, तो कोड उन सभी इफ-स्टेटमेंट्स के साथ बहुत बदसूरत हो सकता है।

एक और जगह यह उपयोगी है फैक्ट्री ऑब्जेक्ट्स को परिभाषित करने के लिए (ऑब्जेक्ट जो आपके लिए ऑब्जेक्ट बनाते हैं)। मान लीजिए कि आपके पास कुछ क्लास फैक्ट्री है, जो कार ऑब्जेक्ट बनाती है और उन्हें वापस करती है। आप इसे ऐसा बना सकते हैं कि myFactory.make_car ('red', 'bmw', '335ix') Car ('red', 'bmw', '335ix') बनाता है, फिर उसे लौटाता है।

def make_car(*args):
   return Car(*args)

यह तब भी उपयोगी है जब आप सुपरक्लास के कंस्ट्रक्टर को बुलाना चाहते हैं।


4
मुझे आपके उदाहरण पसंद हैं। लेकिन, मुझे लगता है कि -1 + 3 == 2.
एकोर्स्सो

5
मैंने जानबूझकर वहाँ कुछ डाला जो विफल हो जाएगा :)
डोनाल्ड माइनर

19

इसे विस्तारित कॉल सिंटैक्स कहा जाता है। से प्रलेखन :

यदि फ़ंक्शन कॉल में वाक्य रचना * अभिव्यक्ति दिखाई देती है, तो अभिव्यक्ति को एक अनुक्रम का मूल्यांकन करना चाहिए। इस क्रम के तत्वों को ऐसे माना जाता है जैसे कि वे अतिरिक्त स्थैतिक तर्क थे; अगर वहाँ स्थितीय तर्क हैं X1, ..., xN, और अभिव्यक्ति एक अनुक्रम y1, ..., yM का मूल्यांकन करता है, तो यह M + N स्थितीय तर्कों X1, ..., xN, y1, के साथ एक कॉल के बराबर है। .., वाई.एम.

तथा:

यदि फ़ंक्शन कॉल में वाक्य रचना ** अभिव्यक्ति दिखाई देती है, तो अभिव्यक्ति को एक मैपिंग का मूल्यांकन करना चाहिए, जिसकी सामग्री को अतिरिक्त कीवर्ड तर्क के रूप में माना जाता है। एक अभिव्यक्ति के रूप में और एक स्पष्ट खोजशब्द तर्क के रूप में प्रदर्शित होने वाले कीवर्ड के मामले में, TypeError अपवाद उठाया जाता है।


3
पाठ्यपुस्तक के उत्तर में केवल एक फुटनोट जोड़ने से - वाक्य-संबंधी समर्थन आने से पहले, अंतर्निहित apply()कार्यक्षमता के साथ समान कार्यक्षमता प्राप्त की गई थी
जेरेमी ब्राउन

18

एक फ़ंक्शन कॉल में सिंगल स्टार एक सूची को अलग-थलग तर्कों में बदल देता है (जैसे zip(*x)कि zip(x1,x2,x3)यदि ऐसा ही है x=[x1,x2,x3]) और डबल स्टार एक शब्द को अलग-अलग कीवर्ड तर्क में बदल देता है (जैसे f(**k)कि जैसा f(x=my_x, y=my_y)है k = {'x':my_x, 'y':my_y}

एक फ़ंक्शन परिभाषा में यह चारों ओर का दूसरा तरीका है: एकल स्टार एक सूची में तर्कों की एक मनमानी संख्या को बदल देता है, और दोहरी शुरुआत एक शब्दकोश में कीवर्ड तर्कों की एक मनमानी संख्या में बदल जाती है। उदाहरण का def foo(*x)अर्थ है "foo एक मनमानी संख्या लेते हैं और वे सूची x (यानी यदि उपयोगकर्ता कहता है foo(1,2,3), xहोगा [1,2,3]) के माध्यम से पहुंच योग्य होगा " और def bar(**k)इसका अर्थ है "बार एक मनमानी संख्या में कीवर्ड तर्क लेता है और वे शब्दकोश k के माध्यम से सुलभ होंगे (यानी यदि उपयोगकर्ता कॉल करता है bar(x=42, y=23), तो kहोगा {'x': 42, 'y': 23}) "।


3
a (बहुत) देर से टिप्पणी, लेकिन मेरा मानना ​​है कि def foo(*x)* x एक सूची देता है, टपल देता है।
jeremycg
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.