अजगर में तर्क सूची के साथ एक फ़ंक्शन को कॉल करें


150

मैं अजगर में एक अन्य फ़ंक्शन के अंदर एक फ़ंक्शन को कॉल करने की कोशिश कर रहा हूं, लेकिन सही सिंटैक्स नहीं मिल सकता है। मैं कुछ ऐसा करना चाहता हूं:

def wrapper(func, args):
    func(args)

def func1(x):
    print(x)

def func2(x, y, z):
    return x+y+z

wrapper(func1, [x])
wrapper(func2, [x, y, z])

इस मामले में पहला कॉल काम करेगा, और दूसरा नहीं होगा। जो मैं संशोधित करना चाहता हूं वह रैपर फ़ंक्शन है, न कि तथाकथित फ़ंक्शन।

जवाबों:


268

अन्य उत्तरों पर थोड़ा विस्तार करने के लिए:

कतार में:

def wrapper(func, *args):

* के आगे का argsअर्थ है "दिए गए बाकी मापदंडों को लें और उन्हें एक सूची में डालें args"।

कतार में:

    func(*args)

यहां * के बगल में args"का अर्थ है" इस सूची को आर्ग कहा जाता है और इसे बाकी मापदंडों में शामिल न करें।

तो आप निम्न कार्य कर सकते हैं:

def wrapper1(func, *args): # with star
    func(*args)

def wrapper2(func, args): # without star
    func(*args)

def func2(x, y, z):
    print x+y+z

wrapper1(func2, 1, 2, 3)
wrapper2(func2, [1, 2, 3])

में wrapper2, सूची स्पष्ट रूप से पारित हो गई है, लेकिन दोनों आवरणों argsमें सूची शामिल है [1,2,3]


26
एक बात जो मुझे बहुत बार नहीं मिली, वह यह है कि * आर्ग्स के साथ एक फ़ंक्शन को कैसे कॉल किया जाए, यदि आपके पास एक सूची या ट्यूपल है जिसे आप पास करना चाहते हैं। इसके लिए आपको इसे इस तरह से कॉल करने की आवश्यकता है: आवरण 1 (func2, * mylist)
अली

* C में # C def wrapper(func, *args)है जो method(params object[] args)है।
जिम अहो

1
ध्यान दें कि *argsफ़ंक्शन परिभाषा में अंतिम तर्क होना चाहिए।
जिम आहो

2
The * next to args means "take the rest of the parameters given and put them in a list called args".यह उन्हें एक सूची में नहीं, बल्कि एक धुन में रखता है।
टॉमाज़ नोकोń

20

किसी फंक्शन को रैप करने का सबसे सरल तरीका

    func(*args, **kwargs)

... मैन्युअल रूप से एक आवरण लिखने के लिए है जो स्वयं के अंदर func () कहेगा :

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after

पायथन फ़ंक्शन में एक ऑब्जेक्ट है, इसलिए आप इसे किसी अन्य फ़ंक्शन के तर्क के रूप में नाम दे सकते हैं और इसे वापस कर सकते हैं। आप किसी भी फ़ंक्शन के लिए एक रैपर जनरेटर भी लिख सकते हैं () :

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper

कृपया यह भी ध्यान दें कि जब आप किसी फ़ंक्शन के सभी तर्कों का नाम नहीं जानते हैं या नहीं जानना चाहते हैं, तो आप तर्कों का उल्लेख कर सकते हैं, जिसे इसके नाम से दर्शाया गया है, जो कि अभिभावकों में तारांकन से पहले है। फ़ंक्शन का नाम:

    *args

उदाहरण के लिए आप एक फ़ंक्शन को परिभाषित कर सकते हैं जो किसी भी तर्क को ले जाएगा:

    def testFunc(*args):
        print args    # prints the tuple of arguments

पायथन फ़ंक्शन तर्कों पर और भी हेरफेर करने के लिए प्रदान करता है। आप किसी फ़ंक्शन को कीवर्ड तर्क लेने की अनुमति दे सकते हैं। फ़ंक्शन बॉडी के भीतर कीवर्ड तर्क एक शब्दकोश में आयोजित किए जाते हैं। समारोह के नाम के बाद कोष्ठक में इस शब्द को दो तारांकनों द्वारा निरूपित किया जाता है, जिसके बाद शब्दकोश का नाम आता है:

    **kwargs

एक ऐसा ही उदाहरण जो कीवर्ड तर्कों को छापता है:

    def testFunc(**kwargs):
        print kwargs    # prints the dictionary of keyword arguments

11

आप चर लंबाई के तर्कों के लिए * args और ** kwargs सिंटैक्स का उपयोग कर सकते हैं।

* Args और ** kwargs का क्या मतलब है?

और आधिकारिक अजगर ट्यूटोरियल से

http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions


तो मुझे इसकी आवश्यकता है कि दोनों * args और ** kwargs प्राप्त करें और उनके साथ इसे कॉल करें?
सूरदिन

1
नहीं, आप या तो उपयोग कर सकते हैं / या, लेकिन उन्हें अक्सर एक साथ जोड़ा जाता है। आपके मामले में, आपको केवल * args की आवश्यकता है।
13

ठीक है, यह काम करता है, लेकिन यह अभी भी मुझे तर्क की सूची पास नहीं करने देता है, और मुझे उन्हें अलग से पारित करना होगा। यह मेरी वर्तमान स्थिति में मुझे ज्यादा परेशान नहीं करता है, लेकिन फिर भी यह जानना अच्छा होगा कि यह कैसे करना है। (मुझे रैपर (func2, x, y, z) और नहीं आवरण (func2, [x, y, z]) करने की आवश्यकता है)
सर्डिन

यदि उत्तरार्द्ध आप चाहते हैं, तो रैपर फंक 2 को कॉल करते समय * आर्ग्स फॉर्म का उपयोग करें, लेकिन 'डिफ रैपर' में नहीं।
एलेक्स मार्टेली

10

आपके प्रश्न का शाब्दिक उत्तर (ठीक वही करने के लिए, जो आपने पूछा था, केवल आवरण बदलना, फ़ंक्शन या फ़ंक्शन कॉल नहीं) बस लाइन को बदलना है

func(args)

पढ़ने के लिए

func(*args)

यह पायथन को दी गई सूची को लेने के लिए कहता है (इस मामले में args) , और अपनी सामग्री को कार्यस्थल में तर्क के रूप में पारित करता है।

यह ट्रिक फंक्शन कॉल के दोनों "पक्षों" पर काम करती है, इसलिए एक फंक्शन इस तरह परिभाषित होता है:

def func2(*args):
    return sum(args)

आप इसे फेंकने के रूप में कई स्थितिगत तर्क स्वीकार करने में सक्षम होंगे, और उन सभी को एक सूची में जगह देंगे args

मुझे उम्मीद है कि इससे चीजों को थोड़ा स्पष्ट करने में मदद मिलेगी। ध्यान दें कि यह dicts / खोजशब्द तर्कों के साथ-साथ उपयोग **करने के बजाय सभी संभव है*


8

आप तर्क unpacking का उपयोग करने की आवश्यकता है ..

def wrapper(func, *args):
    func(*args)

def func1(x):
    print(x)

def func2(x, y, z):
    print x+y+z

wrapper(func1, 1)
wrapper(func2, 1, 2, 3)

0

पिछले उत्तरों के लिए एक छोटा सा जोड़, क्योंकि मुझे एक समस्या का हल नहीं मिला, जो एक नए प्रश्न को खोलने के लायक नहीं है, लेकिन मुझे यहां ले गया।

यहां एक छोटा कोड स्निपेट है, जो एक रैपर देता है lists, zip()और *argsएक रैपर प्रदान करता है जो अज्ञात राशि के कार्यों से अनजान तर्कों के साथ निपट सकता है।

def f1(var1, var2, var3):
    print(var1+var2+var3)

def f2(var1, var2):
    print(var1*var2)

def f3():
    print('f3, empty')

def wrapper(a,b, func_list, arg_list):
    print(a)
    for f,var in zip(func_list,arg_list):
        f(*var)
    print(b)

f_list = [f1, f2, f3]
a_list = [[1,2,3], [4,5], []]

wrapper('begin', 'end', f_list, a_list)

ध्यान रखें, कि zip()असमान लंबाई की सूचियों के लिए सुरक्षा जांच प्रदान नहीं करता है, जिप पुनरावृत्तियों को अजगर में समान लंबाई के लिए जोर देते हुए देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.