पायथन में एक और समारोह के लिए तर्कों के साथ कार्य करना?


203

क्या पायथन में किसी अन्य फ़ंक्शन के लिए तर्कों के साथ फ़ंक्शन करना संभव है?

कुछ के लिए कहें:

def perform(function):
    return function()

लेकिन पारित किए जाने वाले कार्यों में तर्क होंगे:

action1()
action2(p)
action3(p,r)

जवाबों:


289

क्या आपका यह मतलब है?

def perform( fun, *args ):
    fun( *args )

def action1( args ):
    something

def action2( args ):
    something

perform( action1 )
perform( action2, p )
perform( action3, p, r )

10
नामित मापदंडों के बारे में क्या? यह है कि, def action1(arg1, arg2=None, arg3=None), आप कैसे एक तर्क है कि आप, arg3 को सौंपा जा करने के लिए उदाहरण के लिए इरादा पारित कर सकता है?
चामकुट

6
प्रदर्शन (मज़ा, **
आर्ग्स

क्या होगा performऔर अगर action1, action2विभिन्न फाइलों पर? @ एस.लॉट
एलपर

@alper ने उन्हें आयात किया
pfabri

122

यह वही है जो लंबोदर के लिए है:

def Perform(f):
    f()

Perform(lambda: Action1())
Perform(lambda: Action2(p))
Perform(lambda: Action3(p, r))

7
जिज्ञासा से भी बाहर, क्या आप मुझे बता सकते हैं कि इस मामले के लिए लंबोदर अच्छे क्यों नहीं हैं?
जोन वेंज

11
lambdas अच्छी प्रोग्रामिंग भाषाओं की सर्वश्रेष्ठ विशेषताओं में से एक है। दुर्भाग्य से, पायथन का कार्यान्वयन गंभीर रूप से सीमित है। इस मामले में, हालांकि, वे पूरी तरह से फिट हैं
जेवियर

3
मुझे लगता है कि सीमित वाक्य रचना लगभग अपारदर्शी है; वे n00bz को समझाना मुश्किल है। हां, वे यहां काम करते हैं, और वाक्यविन्यास की भ्रामक विशेषताएं अनुपस्थित हैं। यह है - शायद - एकमात्र उदाहरण मैंने एक मेमने के बारे में देखा है जो अस्पष्ट नहीं है।
S.Lott

11
ताकि आप पास किए गए फ़ंक्शन के परिणाम को पुनः प्राप्त कर सकें, यदि प्रदर्शन () को "कॉलिंग एफ ()" के बजाय केवल कॉलिंग एफ () कहा जाए तो बेहतर नहीं होगा।
म्हावेके

मुझे लगता है कि लैम्ब्डा संस्करण काफी साफ-सुथरा है, लेकिन अजीब तरह से परीक्षण में मैं भाग गया यह एक अन्य जवाब में चर्चा की गई fn (* args) विधि से लैम्बडा के माध्यम से कॉल करने के लिए धीमी थी।
रिचर्ड शेफर्ड

39

आप ऐसे ही फंक्शंस से आंशिक फ़ंक्शन का उपयोग कर सकते हैं।

from functools import partial

def perform(f):
    f()

perform(Action1)
perform(partial(Action2, p))
perform(partial(Action3, p, r))

कीवर्ड के साथ भी काम करता है

perform(partial(Action4, param1=p))

1
functools.partialऔर भी बहुमुखी है अगर performआगे के मापदंडों को सौंपने की जरूरत है f। जैसे, कोई बुला सकता है perform(partial(Action3, p))और perform(f)कुछ कर सकता है f("this is parameter r")
रॉबर्ट

13

का प्रयोग करें और inc Perform एक बेकार फंक्शन है, आप सीधे फंक्शन्स में पास हो सकते हैं।

for func in [Action1, partial(Action2, p), partial(Action3, p, r)]:
  func()


3
यह इस बात पर निर्भर करता है कि आप चाहते हैं कि प्रदर्शन के कॉल स्थल पर तर्कों का मूल्यांकन किया जाए या नहीं।
डेव

6

(महीने बाद) एक छोटा सा वास्तविक उदाहरण जहां लंबोदर उपयोगी है, आंशिक नहीं:
कहते हैं कि आप 2 आयामी फ़ंक्शन के माध्यम से विभिन्न 1-आयामी क्रॉस-सेक्शन चाहते हैं, जैसे पहाड़ियों की एक पंक्ति के माध्यम से स्लाइस।
quadf( x, f )1-डी लेता है fऔर विभिन्न के लिए कहता है x
इसे वर्टिकल कट्स के लिए y = -1 0 1 पर और क्षैतिज कट्स को x = -1 0 1 पर कॉल करें।

fx1 = quadf( x, lambda x: f( x, 1 ))
fx0 = quadf( x, lambda x: f( x, 0 ))
fx_1 = quadf( x, lambda x: f( x, -1 ))
fxy = parabola( y, fx_1, fx0, fx1 )

f_1y = quadf( y, lambda y: f( -1, y ))
f0y = quadf( y, lambda y: f( 0, y ))
f1y = quadf( y, lambda y: f( 1, y ))
fyx = parabola( x, f_1y, f0y, f1y )

जहाँ तक मुझे पता है, partialऐसा नहीं कर सकते -

quadf( y, partial( f, x=1 ))
TypeError: f() got multiple values for keyword argument 'x'

(इसमें टैग्स को संख्यात्मक, आंशिक, लंबोदर कैसे जोड़ा जाए?)


5

इसे आंशिक कार्य कहा जाता है और इसे करने के कम से कम 3 तरीके हैं। मेरा पसंदीदा तरीका लैम्ब्डा का उपयोग करना है क्योंकि यह अतिरिक्त पैकेज पर निर्भरता से बचता है और सबसे कम क्रिया है। मान लें कि आपके पास एक फ़ंक्शन है add(x, y)और आप add(3, y)किसी अन्य फ़ंक्शन को पैरामीटर के रूप में पास करना चाहते हैं जैसे कि अन्य फ़ंक्शन के लिए मान तय करता है y

लैम्ब्डा का उपयोग करें

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# run example
def main():
    f = lambda y: add(3, y)
    result = runOp(f, 1) # is 4

अपनी खुद की आवरण बनाएँ

यहां आपको एक फ़ंक्शन बनाने की ज़रूरत है जो आंशिक फ़ंक्शन देता है। यह स्पष्ट रूप से बहुत अधिक क्रिया है।

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# declare partial function
def addPartial(x):
    def _wrapper(y):
        return add(x, y)
    return _wrapper

# run example
def main():
    f = addPartial(3)
    result = runOp(f, 1) # is 4

फंक्शंस से आंशिक का उपयोग करें

यह lambdaऊपर दिखाए गए लगभग समान है । फिर हमें इसकी आवश्यकता क्यों है? इसके कुछ कारण हैं । संक्षेप में, partialकुछ मामलों में थोड़ा तेज हो सकता है (इसका कार्यान्वयन देखें ) और यह कि आप इसका उपयोग शुरुआती बाध्यकारी बनाम लंबोदर के देर से बाध्यकारी के लिए कर सकते हैं।

from functools import partial

# generic function takes op and its argument
def runOp(op, val):
    return op(val)

# declare full function
def add(x, y):
    return x+y

# run example
def main():
    f = partial(add, 3)
    result = runOp(f, 1) # is 4

1

इसे बंद करने का एक तरीका है:

    def generate_add_mult_func(func):
        def function_generator(x):
            return reduce(func,range(1,x))
        return function_generator

    def add(x,y):
        return x+y

    def mult(x,y):
        return x*y

    adding=generate_add_mult_func(add)
    multiplying=generate_add_mult_func(mult)

    print adding(10)
    print multiplying(10)

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