अपने नाम (एक स्ट्रिंग) का उपयोग करके किसी मॉड्यूल के कार्य को कॉल करना


1734

पायथन कार्यक्रम में फ़ंक्शन के नाम के साथ एक स्ट्रिंग दिए गए फ़ंक्शन को कॉल करने का सबसे अच्छा तरीका क्या है। उदाहरण के लिए, मान लें कि मेरे पास एक मॉड्यूल है foo, और मेरे पास एक स्ट्रिंग है जिसकी सामग्री है "bar"। कॉल करने का सबसे अच्छा तरीका क्या है foo.bar()?

मुझे फ़ंक्शन का रिटर्न मान प्राप्त करने की आवश्यकता है, यही कारण है कि मैं अभी उपयोग नहीं करता हूं eval। मुझे यह पता चला कि evalउस फ़ंक्शन कॉल के परिणाम को लौटाने वाले एक अस्थायी फ़ंक्शन को परिभाषित करने के लिए इसका उपयोग कैसे किया जाए , लेकिन मैं उम्मीद कर रहा हूं कि ऐसा करने का एक और अधिक सुंदर तरीका है।

जवाबों:


2078

fooविधि के साथ मान लेना मॉड्यूल bar:

import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()

आप लाइनों 2 और 3 को छोटा कर सकते हैं:

result = getattr(foo, 'bar')()

अगर वह आपके उपयोग के मामले के लिए अधिक समझ में आता है।

आप getattrइस तरह से उपयोग कर सकते हैं वर्ग उदाहरण बाध्य विधियों, मॉड्यूल-स्तरीय विधियों, वर्ग विधियों ... सूची पर जाता है।


9
किसी फ़ंक्शन को परिभाषित करने के लिए निर्धारित करने के लिए hasattr या getattr का उपयोग किया जा सकता है। मैं एक डेटाबेस मानचित्रण (eventType और हैंडलिंग functionName) था और मैं अपने अजगर में एक ईवेंट हैंडलर परिभाषित करने के लिए यकीन है कि मुझे कभी नहीं "भूल गया" बनाना चाहते थे
शॉन

9
यह काम करता है यदि आप पहले से ही मॉड्यूल का नाम जानते हैं। हालाँकि, यदि आप चाहते हैं कि उपयोगकर्ता मॉड्यूल को स्ट्रिंग के रूप में नाम प्रदान करे, तो यह काम नहीं करेगा।
ब्लेयरग

7
यदि आपको किसी भी प्रकार से बचने की आवश्यकता है, तो कोई कॉलटेबल अपवाद नहीं है, तो आप गेटट्र के तीन-तर्क रूप को भी नियोजित कर सकते हैं: गेटैट (foo, 'बार', लैम्ब्डा: कोई नहीं)। मैं स्वरूपण के लिए माफी माँगता हूँ; स्टेक्सएक्सचेंज एंड्रॉइड ऐप स्पष्ट रूप से भयानक है।
geekofalltrades

3
यदि आप केवल अपने स्थानीय / वर्तमान मॉड्यूल के कार्यों के बारे में उदाहरण के लिए परवाह करते हैं, तो @sastanin द्वारा प्रदान किया गया उत्तर भी देखें।
नुस्कूलर

6
@akki हाँ, यदि आप कर रहे हैं मेंfoo मॉड्यूल आप उपयोग कर सकते हैं globals(): यह करने के लिएmethodToCall = globals()['bar']
बेन होयत

543
locals()["myfunction"]()

या

globals()["myfunction"]()

स्थानीय लोग वर्तमान स्थानीय प्रतीक तालिका के साथ एक शब्दकोश देते हैं। ग्लोबल्स वैश्विक प्रतीक तालिका के साथ एक शब्दकोश देता है।


53
ग्लोबल्स / लोकल के साथ यह तरीका अच्छा है अगर आपको जिस विधि को कॉल करने की आवश्यकता है वह उसी मॉड्यूल में परिभाषित है जिसे आप कॉल कर रहे हैं।
जोएलमोब

@ Joelmob रूट नेमस्पेस से स्ट्रिंग द्वारा ऑब्जेक्ट प्राप्त करने का कोई अन्य तरीका है?
निक टी

@ निकट मुझे केवल इन विधियों के बारे में पता है, मुझे नहीं लगता कि कोई अन्य हैं जो समान फ़ंक्शन को पूरा करते हैं, कम से कम मैं एक कारण के बारे में नहीं सोच सकता कि क्यों अधिक होना चाहिए।
जोएलमोब

मुझे आपके लिए एक कारण मिल गया है (वास्तव में मुझे यहां किस कारण से लाया गया है): मॉड्यूल ए में एक फ़ंक्शन एफ है जिसे नाम से एक फ़ंक्शन को कॉल करने की आवश्यकता है। मॉड्यूल बी मॉड्यूल A को आयात करता है, और फ़ंक्शन G को कॉल करने के अनुरोध के साथ फ़ंक्शन F को आमंत्रित करता है, जिसे मॉड्यूल बी में परिभाषित किया गया है। यह कॉल विफल हो जाता है, क्योंकि, फ़ंक्शन F केवल उन मॉड्यूल के साथ चलता है जिन्हें मॉड्यूल F में परिभाषित किया गया है - इसलिए ग्लोबल्स () ['जी'] = कोई नहीं।
डेविड स्टीन

337

पैट्रिक का समाधान शायद सबसे साफ है। यदि आपको मॉड्यूल को गतिशील रूप से लेने की आवश्यकता है, तो आप इसे आयात कर सकते हैं:

module = __import__('foo')
func = getattr(module, 'bar')
func()

93
मुझे समझ में नहीं आता कि आखिरी टिप्पणी। __import__ का अपना अधिकार है और उल्लिखित डॉक्स में अगला वाक्य कहता है: "__import __ () का प्रत्यक्ष उपयोग दुर्लभ है, उन मामलों को छोड़कर, जहां आप एक मॉड्यूल आयात करना चाहते हैं जिसका नाम केवल रनटाइम में जाना जाता है"। तो: दिए गए उत्तर के लिए +1।
हॉफमाजे

50
का उपयोग करें importlib.import_module। आधिकारिक डॉक्स के बारे में कहते हैं __import__: "यह एक उन्नत फ़ंक्शन है जो कि importlib.import_module () के विपरीत, रोज़ पाइथन प्रोग्रामिंग में आवश्यक नहीं है।" docs.python.org/2/library/functions.html#__import__
glarrain

8
@glarrain जब तक आप केवल 2.7 और ऊपर समर्थन के साथ ठीक हैं।
Xiong Ch128ov

1
@Xiong Chaimiov, importlib.import_module3.6 में समर्थित है। देखें docs.python.org/3.6/library/...
cowlinator

7
@cowlinator हाँ, 3.6 "2.7 और ऊपर" का हिस्सा है, दोनों सख्त संस्करण अर्थविज्ञान में और रिलीज़ की तारीखों में (यह लगभग छह साल बाद आया)। यह भी मेरी टिप्पणी के बाद तीन साल के लिए मौजूद नहीं था। ;) 3.x शाखा में, मॉड्यूल 3.1 से आसपास रहा है। 2.7 और 3.1 अब बहुत प्राचीन हैं; आपको अभी भी ऐसे सर्वर मिलेंगे जो केवल 2.6 का समर्थन करते हैं, लेकिन यह आजकल आयात की जाने वाली मानक सलाह होने के लायक है।
Xiong Ch मियामीov

113

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

# Get class from globals and create an instance
m = globals()['our_class']()

# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')

# Call it
func()

उदाहरण के लिए:

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('you called sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')

# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')

और, यदि एक वर्ग नहीं:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')

100

एक स्ट्रिंग, एक पूर्ण अजगर पथ के साथ एक फ़ंक्शन को देखते हुए, इस तरह से मैंने कहा कि फ़ंक्शन के परिणाम प्राप्त करने के बारे में:

import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()

1
इससे मुझे मदद मिली। यह __import__फ़ंक्शन का एक हल्का संस्करण है ।
पंकज भंभानी

मुझे लगता है कि यह सबसे अच्छा जवाब था।
सईद

55

पायथन प्रोग्रामिंग के अनुसार सबसे अच्छा जवाब होगा अक्सर पूछे जाने वाले प्रश्न :

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

इस तकनीक का प्राथमिक लाभ यह है कि स्ट्रिंग्स को कार्यों के नाम से मेल खाने की आवश्यकता नहीं है। यह एक मामले के निर्माण का अनुकरण करने के लिए उपयोग की जाने वाली प्राथमिक तकनीक भी है


43

जवाब (मुझे उम्मीद है) कोई भी कभी नहीं चाहता था

आचरण जैसा व्यवहार

getattr(locals().get("foo") or globals().get("foo"), "bar")()

ऑटो-इंपोर्टिंग को क्यों नहीं जोड़ा गया

getattr(
    locals().get("foo") or 
    globals().get("foo") or
    __import__("foo"), 
"bar")()

मामले में हमारे पास अतिरिक्त शब्दकोष हैं जिन्हें हम जांचना चाहते हैं

getattr(next((x for x in (f("foo") for f in 
                          [locals().get, globals().get, 
                           self.__dict__.get, __import__]) 
              if x)),
"bar")()

हमें गहराई में जाने की जरूरत है

getattr(next((x for x in (f("foo") for f in 
              ([locals().get, globals().get, self.__dict__.get] +
               [d.get for d in (list(dd.values()) for dd in 
                                [locals(),globals(),self.__dict__]
                                if isinstance(dd,dict))
                if isinstance(d,dict)] + 
               [__import__])) 
        if x)),
"bar")()

इस रिकर्सिवली स्कैनिंग द्वारा सुधार किया जा सकता निर्देशिका वृक्ष और ऑटो बढ़ते यूएसबी ड्राइव
विल्क्स

27

इसके लायक क्या है, अगर आपको एक स्ट्रिंग के रूप में फ़ंक्शन (या वर्ग) नाम और ऐप नाम को पास करने की आवश्यकता है, तो आप ऐसा कर सकते हैं:

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)

बस थोड़ा अधिक सामान्य हैhandler = getattr(sys.modules[__name__], myFnName)
Lony

21

इसे इस्तेमाल करे। हालांकि यह अभी भी eval का उपयोग करता है, यह केवल वर्तमान संदर्भ से फ़ंक्शन को समन करने के लिए इसका उपयोग करता है । फिर, आपके पास अपनी इच्छानुसार उपयोग करने के लिए वास्तविक कार्य है।

इससे मेरे लिए मुख्य लाभ यह है कि आप फ़ंक्शन को बुलाने के बिंदु पर किसी भी तरह से संबंधित त्रुटियों को प्राप्त करेंगे। जब आप कॉल करेंगे तब आपको केवल फ़ंक्शन से संबंधित त्रुटियां मिलेंगी ।

def say_hello(name):
    print 'Hello {}!'.format(name)

# get the function by name
method_name = 'say_hello'
method = eval(method_name)

# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)

1
यह जोखिम भरा होगा। स्ट्रिंग में कुछ भी हो सकता है और eval इसे किसी भी विचार के बिना eval-ling खत्म कर देगा।
--यटकिट

4
निश्चित रूप से, आप उन संदर्भों से सावधान रहें, जो आप इसमें उपयोग कर रहे हैं, यह उचित होगा या नहीं, उन जोखिमों को देखते हुए।
tvt173

1
एक फ़ंक्शन यह पैरामीटर को मान्य करने के लिए ज़िम्मेदार नहीं होना चाहिए - यह एक अलग फ़ंक्शन का काम है। यह कहना कि एक स्ट्रिंग के साथ eval का उपयोग करना जोखिम भरा है, यह कह रहा है कि प्रत्येक फ़ंक्शन का उपयोग जोखिम भरा है।
red777

evalजब तक कड़ाई से आवश्यक न हो, आपको कभी भी उपयोग नहीं करना चाहिए । getattr(__module__, method_name)इस संदर्भ में एक बेहतर विकल्प है।
moi

14

जो भी सुझाया गया था, उसमें से किसी ने भी मेरी मदद नहीं की। हालांकि मुझे यह पता चला।

<object>.__getattribute__(<string name>)(<params>)

मैं अजगर 2.66 का उपयोग कर रहा हूं

उम्मीद है की यह मदद करेगा


13
यह किस पहलू से गेटअटर () से बेहतर है?
V13

1
वास्तव में मैं क्या चाहता था। एक जादू की तरह काम करता है! उत्तम!! self.__getattribute__('title')के बराबर हैself.title
ioaniatr

self.__getattribute__('title')किसी भी मामले में काम नहीं करता (पता नहीं क्यों) बाद में, लेकिन func = getattr(self, 'title'); func();करता है। इसलिए, शायद getattr()इसके बजाय उपयोग करना बेहतर है
ioaniatr

10
जो लोग अजगर को नहीं जानते हैं वे कृपया इस कबाड़ को रोक सकते हैं? getattrइसके बजाय उपयोग करें ।
अरण-फे

6

इस सवाल के रूप में एक चर के लिए विधि-नाम असाइनमेंट का उपयोग करके कक्षा में डायनामिक रूप से कॉल कैसे करें [डुप्लिकेट] एक डुप्लिकेट के रूप में चिह्नित इस के रूप में, मैं एक संबंधित उत्तर यहां पोस्ट कर रहा हूं:

परिदृश्य है, एक वर्ग में एक विधि गतिशील रूप से उसी वर्ग पर एक और विधि को कॉल करना चाहती है, मैंने कुछ विवरणों को मूल उदाहरण में जोड़ा है जो कुछ व्यापक परिदृश्य और स्पष्टता प्रदान करता है:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.


    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff


if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

आउटपुट (पायथन 3.7.x)

फ़ंक्शन 1: 12

समारोह 2: 12


-7

यह एक सरल उत्तर है, यह आपको उदाहरण के लिए स्क्रीन को साफ करने की अनुमति देगा। वहाँ नीचे दो उदाहरण, eval और कार्यकारी के साथ, कि सफाई के बाद शीर्ष पर 0 प्रिंट होगा रहे हैं (यदि आप Windows, परिवर्तन का उपयोग कर रहे clearकरने के लिए cls, लिनक्स और मैक उपयोगकर्ताओं को छोड़ के रूप में उदाहरण के लिए) या सिर्फ यह क्रमशः निष्पादित।

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")

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