মডিউলটির নাম (স্ট্রিং) ব্যবহার করে একটি ফাংশন কল করা


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 একটি ফাংশন সংজ্ঞায়িত করা হয়েছে তা নির্ধারণ করতে ব্যবহার করা যেতে পারে। আমার একটি ডাটাবেস ম্যাপিং ছিল (ইভেন্ট টাইপ এবং হ্যান্ডলিং ফাংশন নাম) এবং আমি নিশ্চিত করতে চেয়েছিলাম যে আমি কখনই আমার অজগরটিতে ইভেন্ট হ্যান্ডলার সংজ্ঞায়িত করতে "ভুলিনি"
শন

9
আপনি যদি ইতিমধ্যে মডিউলটির নাম জানেন তবে এটি কাজ করে। তবে, আপনি যদি চান যে ব্যবহারকারী কোনও স্ট্রিং হিসাবে মডিউলটির নাম সরবরাহ করে, এটি কাজ করবে না।
ব্লেয়ারজ 23

7
আপনার যদি নননটাইপ এড়াতে হবে তবে কলযোগ্য ব্যতিক্রম নয়, আপনি গেটিয়েটারের তিনটি যুক্তিযুক্ত রূপটিও ব্যবহার করতে পারেন: গেটআটার (ফু, 'বার', ল্যাম্বদা: কিছুই নয়)। বিন্যাসের জন্য আমি ক্ষমাপ্রার্থী; স্ট্যাকেক্সচেঞ্জ অ্যান্ড্রয়েড অ্যাপটি দৃশ্যত ভয়ানক।
geekofalltrades

3
আপনি যদি কেবল আপনার স্থানীয় / বর্তমান মডিউলটির কার্যকারিতা সম্পর্কে উদ্বিগ্ন হন তবে @ সাস্তানিন দ্বারা সরবরাহ করা উত্তরটিও দেখুন।
নিউস্কুলার

6
@akki হ্যাঁ, যদি তুমি মধ্যেfoo মডিউল আপনি ব্যবহার করতে পারেন globals(): এই কাজ করতেmethodToCall = globals()['bar']
বেন Hoyt

543
locals()["myfunction"]()

অথবা

globals()["myfunction"]()

স্থানীয়রা বর্তমান স্থানীয় প্রতীক টেবিল সহ একটি অভিধান ফেরত দেয়। globals আয় বিশ্বব্যাপী প্রতীক টেবিল সঙ্গে একটি অভিধান।


53
গ্লোবাল / স্থানীয়দের সাথে এই পদ্ধতিটি যদি আপনার কল করার পদ্ধতিটি একই মডিউলে সংজ্ঞায়িত করা হয় তবে আপনি কল করছেন।
জোয়েলমব

@ জোয়েলমবকে মূল নেমস্পেসের বাইরে স্ট্রিং দিয়ে কোনও জিনিস পাওয়ার কী অন্য উপায় আছে?
নিক টি

@ নিকটি আমি কেবল এই পদ্ধতিগুলি সম্পর্কে সচেতন, আমি মনে করি না যে এই জাতীয় ফাংশন পূরণকারী অন্য কোনও লোক রয়েছে, কমপক্ষে আমি আরও বেশি কারণ থাকার কারণ সম্পর্কে ভাবতে পারি না।
জোয়েলমব 27'15

আমি আপনার জন্য একটি কারণ পেয়েছি (আসলে এখানে যা আমাকে নেতৃত্ব দিয়েছিল): মডিউল এ এর ​​একটি ফাংশন রয়েছে যা নাম অনুসারে একটি ফাংশন কল করতে হবে। মডিউল বি মডিউল এ আমদানি করে এবং ফাংশন এফ কে অনুরোধ করে ফাংশন জি কল করার জন্য যা মডিউল বিতে সংজ্ঞায়িত হয়েছে, কলটি ব্যর্থ হয় কারণ দৃশ্যত, ফাংশন এফ কেবল গ্লোবালগুলির সাথে সঞ্চালিত হয় যা মডিউল এফ সংজ্ঞায়িত হয় - তাই গ্লোবাল () ['জি'] = কিছুই নয়।
ডেভিড স্টেইন

336

প্যাট্রিক এর সমাধান সম্ভবত সবচেয়ে পরিষ্কার। আপনার যদি গতিশীলভাবে পাশাপাশি মডিউলটি বাছাই করা প্রয়োজন হয় তবে আপনি এটি এ জাতীয় করে আমদানি করতে পারেন:

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

93
আমি শেষ মন্তব্যটি বুঝতে পারি না। _______ এর নিজস্ব অধিকার রয়েছে এবং উল্লিখিত ডক্সের পরবর্তী বাক্যটিতে বলা হয়েছে: "__import __ () এর সরাসরি ব্যবহার বিরল, আপনি যেখানে এমন একটি মডিউল আমদানি করতে চান যেখানে কেবলমাত্র রানটাইমের সময় পরিচিত"। সুতরাং: প্রদত্ত উত্তরের জন্য +1।
hoffmaje

50
ব্যবহার importlib.import_module। সরকারী দস্তাবেজগুলি সম্পর্কে বলেছেন __import__: "এটি একটি উন্নত ফাংশন যা রোজকার পাইথন প্রোগ্রামিংয়ে ইমপোর্টলিব.মম্পোর্ট_মডিউল () এর বিপরীতে প্রয়োজন হয় না" " docs.python.org/2/library/funitions.html#__import__
glarrain

8
@glarrain যতক্ষণ না আপনি কেবল 2.7 এবং তার বেশি সমর্থন দিয়ে ঠিক থাকেন।
জিয়াং চিয়ামিয়াভ

1
@ জিওনগ চেমিওভ, importlib.import_module3.6-এ সমর্থিত। দেখুন docs.python.org/3.6/library/...
cowlinator

7
@ কমলিনেটর হ্যাঁ, ৩.6 হ'ল "২.7 এবং তার বেশি" অংশ, উভয়ই কঠোর সংস্করণ সংস্করণ এবং প্রকাশের তারিখগুলিতে (এটি প্রায় ছয় বছর পরে এসেছিল)। আমার মন্তব্যের পরে তিন বছর এটিরও অস্তিত্ব ছিল না। ;) 3.x শাখায়, মডিউলটি 3.1 সাল থেকে প্রায় রয়েছে। ২.7 এবং ৩.১ এখন বেশ প্রাচীন; আপনি এখনও কেবল 2.6 সমর্থন করে এমন চারপাশে সার্ভারগুলি দেখতে পাবেন তবে আজকাল এটি সম্ভবত স্ট্যান্ডার্ড পরামর্শ হিসাবে আমদানিযোগ্য worth
জিয়াং চিয়ামিয়াভ

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

এটা চেষ্টা কর. এটি এখনও অবাস্তব ব্যবহার করে, এটি কেবলমাত্র বর্তমান প্রেক্ষাপট থেকে ফাংশন ডেকে আনতে এটি ব্যবহার করে । তারপরে, আপনার ইচ্ছামত ব্যবহার করার জন্য আপনার আসল ফাংশন রয়েছে।

এ থেকে আমার জন্য প্রধান উপকারিতা হ'ল ফাংশনটি তলব করার সময়ে আপনি কোনও ইওল-সম্পর্কিত ত্রুটি পাবেন। তারপরে আপনি কল করলে আপনি কেবল ফাংশন-সম্পর্কিত ত্রুটি পাবেন।

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
এটি ঝুঁকিপূর্ণ হবে। স্ট্রিংয়ের যে কোনও কিছু থাকতে পারে এবং এভাল কোনও বিবেচনা ছাড়াই এটির সাথে ইভিওল-লিং শেষ করে।
iankit

4
অবশ্যই, আপনি যে প্রসঙ্গে এটি ব্যবহার করছেন সে বিষয়ে অবশ্যই আপনাকে সচেতন হতে হবে, এই ঝুঁকিগুলি বিবেচনা করে এটি যথাযথ হবে কি না।
tvt173

1
কোনও ফাংশন এর পরামিতিগুলি যাচাই করার জন্য দায়বদ্ধ হওয়া উচিত নয় - এটি একটি ভিন্ন ফাংশনের কাজ। এটি স্ট্রিং দিয়ে ইওল ব্যবহার করা ঝুঁকিপূর্ণ বলে দিচ্ছে যে প্রতিটি ফাংশনটির ব্যবহার ঝুঁকিপূর্ণ।
red777

evalকঠোরভাবে প্রয়োজন না হলে আপনার কখনও ব্যবহার করা উচিত নয় । getattr(__module__, method_name)এই প্রসঙ্গে অনেক ভাল পছন্দ।
moi

14

যা প্রস্তাবিত হয়েছিল তার কিছুই আমাকে সাহায্য করেনি। আমি যদিও এটি আবিষ্কার করেছি।

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

আমি পাইথন ২.66। ব্যবহার করছি

আশাকরি এটা সাহায্য করবে


13
এটি কোন দিক থেকে গেটআটার () এর চেয়ে ভাল?
ভি 13

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 এবং Exec সঙ্গে, যে পরিষ্কারের পর উপরের 0 প্রিন্ট হবে (যদি আপনি উইন্ডোজ, পরিবর্তন ব্যবহার করছেন clearথেকে cls, Linux এবং Mac ব্যবহারকারীদের ছেড়ে যেমন উদাহরণস্বরূপ হয়) বা শুধু এটি যথাক্রমে চালানো।

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

3
এটি ওপ জিজ্ঞাসা করে না।
টুনচে Göncüoğlu
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.