python الدوال - استدعاء دالة وحدة نمطية باستخدام اسمها(سلسلة)




في بايثون (9)

ما هي أفضل طريقة للذهاب حول استدعاء وظيفة معينة في سلسلة مع اسم الدالة في برنامج Python. على سبيل المثال ، لنفترض أن لدي وحدة foo ، ولديّ سلسلة تحتوي على "bar" . ما هي أفضل طريقة للانتقال بـ foo.bar() ؟

أحتاج إلى الحصول على قيمة الإرجاع للدالة ، ولهذا السبب لا أستخدم فقط eval . فكنت أحسب كيفية القيام بذلك باستخدام eval لتعريف دالة مؤقتة تقوم بارجاع نتيجة استدعاء الدالة ، لكنني آمل أن يكون هناك طريقة أكثر أناقة للقيام بذلك.


Answers

أفضل إجابة طبقًا لأسئلة برمجة Python هي:

functions = {'myfoo': foo.bar}

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

الميزة الأساسية لهذه التقنية هي أن السلاسل لا تحتاج إلى مطابقة أسماء الوظائف. هذا هو أيضا التقنية الأساسية المستخدمة لمحاكاة بناء حالة


الجواب (آمل) لا أحد يريد من أي وقت مضى

سلوك شبيه بالفضول

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

مجرد مساهمة بسيطة. إذا كان الفصل الذي نحتاج إليه في الملف نفسه ، فيمكننا استخدام شيء كالتالي:

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

locals()["myfunction"]()

أو

globals()["myfunction"]()

locals بإرجاع قاموس مع جدول رمز محلي الحالي. globals إرجاع قاموس مع جدول رمز عمومي.


جرب هذا. في حين أن هذا لا يزال يستخدم eval ، فإنه يستخدم فقط لاستدعاء الدالة من السياق الحالي . ثم ، لديك وظيفة حقيقية لاستخدام ما تشاء.

الفائدة الرئيسية بالنسبة لي من هذا هو أنك سوف تحصل على أي أخطاء تتعلق بال 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)

لما يستحق ، إذا كنت بحاجة إلى تمرير اسم الوظيفة (أو الفصل) واسم التطبيق كسلسلة ، فيمكنك القيام بذلك:

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

بافتراض وحدة foo مع bar الطريقة:

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

بقدر ما يتم ذلك ، يمكن ضغط الخط 2 و 3 إلى:

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

إذا كان ذلك أكثر منطقية لحالة الاستخدام الخاصة بك. يمكنك استخدام getattr في هذا الشكل على الطرق المربوطة لطبقة الصف ، والطرق على مستوى الوحدة النمطية ، وطرق getattr ... والقائمة تطول.


لم يساعدني شيء مما اقترح. لقد اكتشفت هذا رغم ذلك.

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

أنا أستخدم python 2.66

أتمنى أن يساعدك هذا


هناك اختلاف آخر هنا لم يرد ذكره من قبل.

subprocess.Popenينفذ <command> مثل عملية فرعية. في حالتي ، أحتاج إلى تنفيذ الملف <a> الذي يحتاج إلى التواصل مع برنامج آخر ، <b>.

حاولت تجربة فرعية ، وكان التنفيذ ناجحا. ومع ذلك ، تعذر على <b> التواصل مع <a>. كل شيء طبيعي عند تشغيل كلا من المحطة.

واحد آخر: (ملاحظة: kwrite يتصرف بشكل مختلف عن التطبيقات الأخرى. إذا حاولت أدناه مع فايرفوكس ، فإن النتائج لن تكون هي نفسها.)

إذا حاولت os.system("kwrite")، يتجمد تدفق البرنامج حتى يقوم المستخدم بإغلاق kwrite. للتغلب على ذلك حاولت بدلا من ذلك os.system(konsole -e kwrite). استمر هذا البرنامج في التدفق ، لكن kwrite أصبح البرنامج الفرعي للكونسول.

أي شخص يدير kwrite لا يجري عملية فرعية (أي في شاشة النظام يجب أن تظهر على الحافة اليسرى من الشجرة).





python