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

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

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

0
जोड़ा संपादित
विचारों: 1

9 उत्तर

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

module = __import__('foo')
func = getattr(module, 'bar')
func()
0
जोड़ा
@glarrain जब तक आप केवल 2.7 और ऊपर समर्थन के साथ ठीक हो।
जोड़ा लेखक Xiong Chiamiov, स्रोत
@cowलिनेटर हां, 3.6 "2.7 और ऊपर" का हिस्सा है, सख्त संस्करणिंग अर्थशास्त्र में और रिलीज तिथियों में (यह लगभग छह साल बाद आया था)। यह मेरी टिप्पणी के तीन साल बाद भी अस्तित्व में नहीं था। ;) 3.x शाखा में, मॉड्यूल 3.1 के आसपास से रहा है। 2.7 और 3.1 अब बहुत प्राचीन हैं; आप अभी भी केवल 2.6 का समर्थन करने वाले सर्वरों को लटका पाएंगे, लेकिन संभवतया यह importlib मानक सलाह होने के लायक है।
जोड़ा लेखक Xiong Chiamiov, स्रोत
@Xiong Chaimiov, importlib.import_module 3.6 में समर्थित है। docs.python.org/3.6/library/…
जोड़ा लेखक cowlinator, स्रोत
importlib.import_module का उपयोग करें। आधिकारिक दस्तावेज़ __ आयात __ के बारे में कहते हैं: "यह एक उन्नत कार्य है जिसे रोज़ाना पायथन प्रोग्रामिंग में आवश्यक नहीं है, importlib.import_module() के विपरीत।" docs.python.org/2/library/functions.html#__import__
जोड़ा लेखक glarrain, स्रोत
मैं उस अंतिम टिप्पणी को समझ नहीं पा रहा हूं। __import__ का अपना अधिकार है और उल्लिखित दस्तावेज़ों में अगली वाक्य कहती है: "__import __() का प्रत्यक्ष उपयोग दुर्लभ है, उन मामलों को छोड़कर जहां आप एक मॉड्यूल आयात करना चाहते हैं जिसका नाम केवल रनटाइम पर जाना जाता है"। तो: दिए गए उत्तर के लिए +1।
जोड़ा लेखक hoffmaje, स्रोत

सुझाव दिया गया कोई भी मेरी मदद नहीं की। मैंने हालांकि यह खोजा था।

.__getattribute__()() 

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

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

0
जोड़ा
Getattr() से बेहतर यह किस पहलू में है?
जोड़ा लेखक V13, स्रोत

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

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
0
जोड़ा
बस थोड़ा और सामान्य है हैंडलर = getattr (sys.modules [__ name__], myFnName)
जोड़ा लेखक lony, स्रोत

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

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()
0
जोड़ा
इससे मेरी मदद की। यह __ आयात __ फ़ंक्शन का हल्का संस्करण है।
जोड़ा लेखक Pankaj Bhambhani, स्रोत
साफ समाधान साथी!
जोड़ा लेखक Nebulosar, स्रोत
locals()["myfunction"]()

या

globals()["myfunction"]()

locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.

0
जोड़ा
@Joelmob रूट नेमस्पेस से स्ट्रिंग करके ऑब्जेक्ट प्राप्त करने का कोई अन्य तरीका है?
जोड़ा लेखक Nick T, स्रोत
ग्लोबल्स / स्थानीय लोगों के साथ यह विधि अच्छी है यदि आपको जिस विधि को कॉल करने की आवश्यकता है उसे उसी मॉड्यूल में परिभाषित किया गया है जिसे आप कॉल कर रहे हैं।
जोड़ा लेखक Joelmob, स्रोत
@ निकट मैं केवल इन तरीकों से अवगत हूं, मुझे नहीं लगता कि ऐसे कोई भी अन्य हैं जो इन कार्यों को भरते हैं, कम से कम मैं इस कारण के बारे में नहीं सोच सकता कि और क्यों होना चाहिए।
जोड़ा लेखक Joelmob, स्रोत
मेरे पास आपके लिए एक कारण है (वास्तव में मुझे यहां किसने नेतृत्व किया): मॉड्यूल ए में एक फ़ंक्शन एफ है जिसे नाम से फ़ंक्शन कॉल करने की आवश्यकता होती है। मॉड्यूल बी आयात मॉड्यूल ए, और फंक्शन जी को कॉल करने के अनुरोध के साथ फ़ंक्शन एफ को आमंत्रित करता है, जिसे मॉड्यूल बी में परिभाषित किया गया है। यह कॉल विफल हो जाती है क्योंकि जाहिर है, फ़ंक्शन F केवल मॉड्यूल एफ में परिभाषित ग्लोबल्स के साथ चलता है - इसलिए ग्लोबल्स() ['जी'] = कोई नहीं।
जोड़ा लेखक David Stein, स्रोत

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

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

जहां तक ​​यह जाता है, रेखा 2 और 3 को संपीड़ित किया जा सकता है:

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

अगर यह आपके उपयोग के मामले के लिए अधिक समझ में आता है। आप क्लास इंस्टेंस बाध्य विधियों, मॉड्यूल-स्तरीय विधियों, कक्षा विधियों पर इस फैशन में getattr का उपयोग कर सकते हैं ... सूची चालू है।

0
जोड़ा
इसके वर्तमान मूल्य के लिए, कोई भी इस महान उत्तर का धन्यवाद नहीं करता है।
जोड़ा लेखक Coolio2654, स्रोत
यह उन सजावट के साथ काम नहीं करता जो सजावट का उपयोग करते हैं। Getattr बाहरी समारोह देता है
जोड़ा लेखक azmeuk, स्रोत
हैटर या गेटैटर का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि कोई फ़ंक्शन परिभाषित किया गया है या नहीं। मेरे पास डेटाबेस मैपिंग (इवेंट टाइप और हैंडलिंग फ़ंक्शननाम) था और मैं यह सुनिश्चित करना चाहता था कि मैं अपने अजगर में इवेंट हैंडलर को परिभाषित करने के लिए कभी भी "भूल गया"
जोड़ा लेखक Shaun, स्रोत
भावहीन। मैंने foo.getattr ('bar') और foo.get_attr ('bar') की विविधताओं को आजमाने में 10 मिनट बिताए।
जोड़ा लेखक Eric Duminil, स्रोत
@sastanin द्वारा प्रदान किए गए उत्तर को भी देखें यदि आप केवल अपने स्थानीय / वर्तमान मॉड्यूल के कार्यों के बारे में उदाहरण की देखभाल करते हैं।
जोड़ा लेखक NuSkooler, स्रोत
नोट: कूल +1, इसने मुझे एक बार और समझ लिया कि पाइथन में सबकुछ एक वस्तु है। नतीजतन, यह चर के साथ भी काम करता है, आप किसी अन्य ऑब्जेक्ट के चर के रूप में मॉड्यूल के चर का उपयोग कर सकते हैं।
जोड़ा लेखक tuned, स्रोत
@akki हां, अगर आप में foo मॉड्यूल हैं तो आप इसे करने के लिए globals() का उपयोग कर सकते हैं: methodToCall = globals ( ) [ 'बार']
जोड़ा लेखक Ben Hoyt, स्रोत
@ पैट्रिक जोहानमेयर मैंने कभी पैटर्न / प्रतिमानों को पूरी तरह से बाहर नहीं किया ... यही कारण है कि मैंने कंबल स्टेटमेंट बनाने के बजाय एक प्रश्न पूछा। इस पैटर्न का उपयोग अत्यधिक मात्रा में करने के लिए बहुत सारे नकारात्मक प्रतिक्रियाएं हैं ... जो (कम से कम मेरे अनुभव में) आम है।
जोड़ा लेखक KeatsKelleher, स्रोत
आप यह कर सकते हैं, लेकिन आपको चाहिए? आपका कोड बेस बड़ा होने पर आपको अपने फ़ंक्शन कॉल के सभी उदाहरण कैसे मिलेगा? इसके लिए grep करने के लिए कुछ भी नहीं है, और उस संदर्भ को खोजने के लिए कोई आईडीई नहीं जा रहा है। इससे इस प्रकार की गतिशील कॉल वास्तव में परेशानी होती है। क्या यह आपके सहयोगियों के लिए स्पष्ट नहीं है, वैसे भी? कम कोड का मतलब हमेशा अधिक पठनीय नहीं होता है।
जोड़ा लेखक KeatsKelleher, स्रोत
यह काम करता है यदि आप पहले ही मॉड्यूल नाम जानते हैं। हालांकि, यदि आप चाहते हैं कि उपयोगकर्ता मॉड्यूल नाम को स्ट्रिंग के रूप में प्रदान करे, तो यह काम नहीं करेगा।
जोड़ा लेखक Blairg23, स्रोत
@KeatsKelleher क्योंकि हम उपयोग के मामले को नहीं जानते हैं, केवल सवाल, मैं विश्वसनीय रूप से कह सकता हूं कि आपके उपयोग पर कई उपयोग के मामले हैं, और कुछ जो वे नहीं करते हैं। नियम इंजन, डीएसएल, इन-ऐप स्क्रिप्टिंग इत्यादि जैसी चीजों को करना आम और उचित है, जिसमें आप जो कोड लिख रहे हैं वह अन्य कोड चलाने के लिए मौजूद है। ऐसा करने के लिए शायद कई अन्य "अच्छे" समय हैं जिन्हें मैं अभी नहीं सोच रहा हूं। तो, चाहिए हम यह करते हैं? उत्तर, अधिकांश भाषाओं में अधिकांश भाषा सुविधाओं के साथ, "यह निर्भर करता है।"
जोड़ा लेखक Patrick Johnmeyer, स्रोत
यदि आपको किसी भी प्रकार से बचने की आवश्यकता नहीं है, तो टाइप करने योग्य अपवाद नहीं है, तो आप Getattr के तीन-तर्क फ़ॉर्म को भी नियोजित कर सकते हैं: getattr (foo, 'bar', lambda: none)। स्वरूपण के लिए मैं क्षमा चाहता हूं; stackexchange एंड्रॉइड ऐप स्पष्ट रूप से भयानक है।
जोड़ा लेखक geekofalltrades, स्रोत
यदि आपके पास गहरी संरचनाएं हैं, तो निम्न वाक्यविन्यास उपयोगी हो सकता है: functools आयात से कम करें (getattr, "a.b.c.d.e.f.g" .split ('।'), DeepStructure)
जोड़ा लेखक Robert Parcus, स्रोत
यह एक बहुत उपयोगी उत्तर है, खरीदें जब मैं मॉड्यूल फू वर्तमान मॉड्यूल स्वयं हूं तो मैं इसे काम नहीं कर सका। क्या कोई जानता है कि ऐसा कैसे करें?
जोड़ा लेखक akki, स्रोत

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

# 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')
0
जोड़ा

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

व्यवहार की तरह eval

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")()
0
जोड़ा

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

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

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)
0
जोड़ा
यह जोखिम भरा होगा। स्ट्रिंग में कुछ भी हो सकता है और eval बिना किसी विचार के इसे eval-ling समाप्त हो जाएगा।
जोड़ा लेखक iankit, स्रोत
निश्चित रूप से, आपको उस संदर्भ के बारे में सावधान रहना चाहिए जिसका आप इसका उपयोग कर रहे हैं, चाहे वह उचित होगा या नहीं, उन जोखिमों को दिया गया है।
जोड़ा लेखक tvt173, स्रोत