python - विफई कालिंग सैमसंग




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

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

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

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

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

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


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

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

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

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()

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

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

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")()

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

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

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

# 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')

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

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

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

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

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

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


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

functions = {'myfoo': foo.bar}

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

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






object