2016-10-25 5 views
11

मुझे *args के माध्यम से कार्य करने के लिए विशाल list/tuple पास करने की आवश्यकता है।फ़ंक्शन कॉल में * args के लिए निष्पादन मॉडल क्या है?

def f(*args): # defined in foreign module 
    pass 

arguments = tuple(range(10000)) 
f(*arguments) 

और मुझे आश्चर्य है कि फ़ंक्शन कॉल पर क्या होता है।

क्या यह किसी भी स्थितित्मक चर के समान arguments संभालता है: इसे बचाएं और शरीर निष्पादन के दौरान मांग पर पहुंचें? या यह शरीर निष्पादन से पहले arguments के माध्यम से स्थितित्मक तर्कों को विस्तारित करता है? या यह कुछ और है?

+1

चूंकि 'तर्क' एक सूची है, लेकिन 'args' एक tuple है, हाँ, पुनरावृत्ति * होना है। ऐसा नहीं है कि यहां 'तर्क' बनाना एक टुपल मदद करेगा। –

+0

आप उस कस्टम ऑब्जेक्ट को लिखकर परीक्षण करने का प्रयास कर सकते हैं जो आपको बताता है कि इसे कब चालू किया जा रहा है। – jonrsharpe

+1

तो यहां तक ​​कि यदि 'तर्क' एक टुपल है, तो यह पुनरावृत्ति वैसे भी होता है? – Ormazd

उत्तर

8

हाँ, *arguments कॉल वाक्य रचना arguments iterable से अधिक पुनरावृति करने के लिए, दो कारणों के लिए है:

  • आपको एक सूची में से गुजर रहे हैं, लेकिन समारोह में *args चर-आकार तर्क एक है टपल। तो तत्वों को यहां कॉपी करना होगा।

  • कॉल वाक्य रचना किसी भी समारोह, आप के बजाय वास्तविक स्थितीय तर्क हो सकता है जहां, या करने के लिए, एक *varargs चर अलावा के लिए प्रयोग करने योग्य हो गया है।

    उदाहरण के लिए, यदि फ़ंक्शन हस्ताक्षर def f(foo, *args): था, तो पहले तत्व को अलग से पारित करना होगा।

    सिद्धांत रूप में, CPython मामले में जहां एक टपल के सभी मानों एक *varargs बहस में function(*tupleargs) अंत के साथ एक फोन में इस्तेमाल के लिए अनुकूलित कर सकता है, और है कि टपल का फिर से उपयोग। हालांकि, यह वास्तव में सभी नहीं है जो आम है और किसी ने भी ऐसा नहीं किया है।

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

13

एक जनरेटर का उपयोग एक साधारण परीक्षण:

def gen(): 
    print('Yielding 1') 
    yield 1 
    print('Yielding 2') 
    yield 2 
    print('Yielding 3') 
    yield 3 


arguments = gen() 
def f(*args): 
    pass 

f(*arguments) 
# Yielding 1 
# Yielding 2 
# Yielding 3 

आप उत्पादन से देख सकते हैं, *arguments गुजर वास्तव में पूरी iterable खोल देगा, तकनीकी रूप से के बाद से, आप अजगर कह रहे व्यक्ति का उपयोग कर तर्कों के रूप iterable पारित करने के लिए *arguments वाक्यविन्यास। इससे कोई फर्क नहीं पड़ता कि फ़ंक्शन परिभाषा *args का भी उपयोग करती है जो पाइथन को फिर से टुपल में तर्कों को पैक करता है।

तो हाँ, आप केवल इसे फिर से पैक करने के लिए सूची को अनपॅक कर रहे हैं। आप सीधे सूची को पास करके इस से बच सकते हैं।

+4

वहाँ एक * संभावना * है से अधिक पुनरावृति नहीं करने के लिए एक * टपल * जब कॉल में उपयोग किए (जैसे '* (1, 2, 3)') क्योंकि मूल्यों, समारोह में '* args' चर में समाप्त लेकिन पायथन ऐसा कोई अनुकूलन नहीं करता है। –

संबंधित मुद्दे