මොඩියුලයක ශ්‍රිතයක් එහි නම (නූලක්) භාවිතා කරමින් කැඳවීම


1755

පයිතන් වැඩසටහනක ඇති ශ්‍රිතයේ නම සහිත නූලක් ලබා දීම සඳහා හොඳම ක්‍රමය කුමක්ද? උදාහරණයක් ලෙස, මට මොඩියුලයක් fooඇති බවත්, එහි අන්තර්ගතය ඇති නූලක් ඇති බවත් කියමු "bar". ඇමතීමට හොඳම ක්‍රමය foo.bar()කුමක්ද?

මට ශ්‍රිතයේ ප්‍රතිලාභ අගය ලබා ගැනීමට අවශ්‍යයි, ඒ නිසා මම භාවිතා නොකරමි eval. evalඑම ශ්‍රිත ඇමතුමේ ප්‍රති result ලය ලබා දෙන තාවකාලික ශ්‍රිතයක් නිර්වචනය කිරීමෙන් එය කරන්නේ කෙසේදැයි මම හදුනා ගත්තෙමි , නමුත් මෙය කිරීමට වඩාත් අලංකාර ක්‍රමයක් ඇතැයි මම බලාපොරොත්තු වෙමි.

Answers:


2102

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 සහ hand functionName) ඇති අතර මගේ පයිතන්හි සිදුවීම් හසුරුවන්නෙකු නිර්වචනය කිරීමට මට කිසි විටෙකත් "අමතක නොවූ" බවට වග බලා ගැනීමට අවශ්‍ය විය
ෂෝන්

9
ඔබ දැනටමත් මොඩියුලයේ නම දන්නේ නම් මෙය ක්‍රියාත්මක වේ. කෙසේ වෙතත්, පරිශීලකයාට මොඩියුලයේ නම නූලක් ලෙස ලබා දීමට අවශ්‍ය නම්, මෙය ක්‍රියා නොකරනු ඇත.
බ්ලෙයාර්ග් 23

7
ඔබට කිසිඳු ටයිප් එකක් මග හැරිය යුතු නම්, එය ව්‍යතිරේකයක් නොවේ නම්, ඔබට ගෙටැටරයේ තර්ක තුනේ ස්වරූපය ද භාවිතා කළ හැකිය: getattr (foo, 'bar', lambda: none). හැඩතල ගැන්වීම ගැන මම සමාව ඉල්ලමි; stackexchange android යෙදුම පෙනෙන විදිහට භයානකයි.
geekofalltrades

3
ඔබේ දේශීය / වත්මන් මොඩියුලයේ කාර්යයන් ගැන ඔබ පමණක් සැලකිලිමත් වන්නේ නම් @ සාස්ටානින් විසින් සපයන ලද පිළිතුරද බලන්න.
NuSkooler

6
@akki ඔව්, ඔබ ඉන්නේ නම් දී ඇති fooමොඩියුලය භාවිතා කළ හැකි globals()මෙය කිරීමට:methodToCall = globals()['bar']
බෙන් Hoyt

548
locals()["myfunction"]()

හෝ

globals()["myfunction"]()

වත්මන් දේශීය සංකේත වගුවක් සහිත ශබ්ද කෝෂයක් ප්‍රදේශවාසීන් ආපසු ලබා දේ. ගෝලීය සංකේත වගුව සහිත ශබ්ද කෝෂයක් ග්ලෝබල් විසින් ලබා දෙයි.


53
ඔබ ඇමතීමට අවශ්‍ය ක්‍රමය ඔබ අමතන්නේ එකම මොඩියුලයක නම්, ගෝලීය / දේශීයයන් සමඟ මෙම ක්‍රමය හොඳයි.
ජොයෙල්මොබ්

Name ජොයෙල්මොබ් විසින් මූල නාම අවකාශයෙන් නූලෙන් වස්තුවක් ලබා ගැනීමට වෙනත් ක්‍රමයක් තිබේද?
නික් ටී

IckNickT මම මේ ක්‍රම ගැන පමණක් දනිමි, මේ හා සමාන ක්‍රියාකාරිත්වයක් පුරවන වෙනත් අය සිටින බව මම නොසිතමි, අවම වශයෙන් වැඩි යමක් තිබිය යුතු හේතුවක් ගැන මට සිතිය නොහැක.
ජොයෙල්මොබ්

මට ඔබ වෙනුවෙන් හේතුවක් තිබේ (ඇත්ත වශයෙන්ම මා මෙහි ගෙන ගියේ කුමක් ද): මොඩියුලය A ශ්‍රිතයක් ඇත, එය ශ්‍රිතයක් නමින් හැඳින්විය යුතුය. මොඩියුලය බී මොඩියුලය ආනයනය කරන අතර මොඩියුලය බී හි අර්ථ දක්වා ඇති ශ්‍රිත ජී ඇමතීමට ඉල්ලීමක් සමඟ එෆ් ශ්‍රිතය ආයාචනය කරයි. මෙම ඇමතුම අසාර්ථක වන්නේ පෙනෙන පරිදි, එෆ් ශ්‍රිතය ක්‍රියාත්මක වන්නේ එෆ් මොඩියුලයේ අර්ථ දක්වා ඇති ගෝලීය සමඟ පමණි - එබැවින් ගෝලීය () ['ජී'] = නැත.
ඩේවිඩ් ස්ටේන්

341

පැට්රික්ගේ විසඳුම බොහෝ විට පිරිසිදු ය. ඔබට මොඩියුලය ගතිකව තෝරා ගැනීමට අවශ්‍ය නම්, ඔබට එය ආයාත කළ හැකිය:

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

93
ඒ අන්තිම අදහස් මට තේරෙන්නේ නැහැ. . එබැවින්: දී ඇති පිළිතුර සඳහා +1.
hoffmaje

50
භාවිතා කරන්න importlib.import_module. නිල ලියකියවිලි මෙසේ කියයි __import__: "මෙය උසස් ක්‍රියාකාරීත්වයක් වන අතර එය එදිනෙදා පයිතන් ක්‍රමලේඛනයේ අවශ්‍ය නොවේ. Importlib.import_module () මෙන් නොව." docs.python.org/2/library/functions.html#__import__
glarrain

8
@glarrain ඔබ හොඳින් සිටින තාක් කල් සහය 2.7 සහ ඊට වැඩි.
සියොන් චියාමොව්

1
@Siong Chaimiov, importlib.import_module3.6 හි සහය දක්වයි. Docs.python.org/3.6/library/…
cowlinator

7
owCowlinator ඔව්, 3.6 යනු “2.7 සහ ඊට වැඩි” කොටසකි, දැඩි අනුවාද අර්ථකථන සහ මුදාහැරීමේ දිනයන්හි (එය පැමිණියේ වසර හයකට පමණ පසුවය). මගේ අදහස් දැක්වීමෙන් පසු එය වසර තුනක් තිස්සේ පැවතුනේ නැත. ;) 3.x ශාඛාවේ, මොඩියුලය 3.1 සිට පැවතුනි. 2.7 සහ 3.1 දැන් තරමක් පැරණි ය; 2.6 ට පමණක් සහය දක්වන සේවාදායකයන් ඔබ තවමත් සොයාගනු ඇත, නමුත් වර්තමානයේ ආනයන ලිබ් යනු සම්මත උපදෙස් වීම වටී.
සියොන් චියාමොව්

116

සරල දායකත්වයක් පමණි. අපට නිදසුනක් ලෙස අවශ්‍ය පන්තිය එකම ගොනුවක තිබේ නම්, අපට මෙවැනි දෙයක් භාවිතා කළ හැකිය:

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

103

ශ්‍රිතයක් සඳහා සම්පූර්ණ පයිතන් මාර්ගයක් සහිත නූලක් ලබා දී ඇති විට, එම ශ්‍රිතයේ ප්‍රති result ල ලබා ගැනීම සඳහා මම ගියෙමි:

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

මෙම ක්‍රමයේ මූලික වාසිය නම්, ශ්‍රිතයන්ගේ නම් සමඟ ගැලපීමට නූල් අවශ්‍ය නොවේ. සිද්ධි ව්‍යුහයක් අනුකරණය කිරීම සඳහා භාවිතා කරන මූලික තාක්‍ෂණය මෙයයි


44

කිසිවෙකුට කවදාවත් අවශ්‍ය නොවූ පිළිතුර (මම බලාපොරොත්තු වෙමි)

හැසිරීම වැනි ඊවාල්

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

1
ඩිරෙක්ටරි ගස නැවත නැවත පරිලෝකනය කිරීමෙන් සහ ස්වයංක්‍රීයව සවිකරන usb ඩ්‍රයිව් මගින් මෙය වැඩිදියුණු කළ හැකිය
wilks

27

එය වටින දෙය සඳහා, ඔබට ශ්‍රිතය (හෝ පන්තියේ) නම සහ යෙදුම් නාමය නූලක් ලෙස සම්මත කිරීමට අවශ්‍ය නම්, ඔබට මෙය කළ හැකිය:

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

තව ටිකක් සාමාන්‍යයිhandler = getattr(sys.modules[__name__], myFnName)
හුදකලා

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
මෙය අවදානම් සහිත වනු ඇත. නූල් වලට ඕනෑම දෙයක් තිබිය හැකි අතර, එවාල් කිසිදු සැලකිල්ලකින් තොරව එය ඉවාල්-ලින්ග් කිරීම අවසන් කරයි.
iankit

4
එම අවදානම් සැලකිල්ලට ගෙන ඔබ එය භාවිතා කරන සන්දර්භය ගැන සැලකිලිමත් විය යුතුය.
tvt173

1
ශ්‍රිතයක් එහි පරාමිතීන් වලංගු කිරීම සඳහා වගකිව යුතු නොවේ - එය වෙනස් ශ්‍රිතයක කාර්යය වේ. නූල් සමඟ එවාල් භාවිතා කිරීම අවදානම් යැයි කීම යනු සෑම ශ්‍රිතයක්ම භාවිතා කිරීම අවදානම් බවයි.
red777

evalදැඩි ලෙස අවශ්‍ය නම් මිස ඔබ කිසි විටෙකත් භාවිතා නොකළ යුතුය. getattr(__module__, method_name)මෙම සන්දර්භය තුළ වඩා හොඳ තේරීමක්.
moi

14

යෝජනා කළ කිසිවක් මට උදව් කළේ නැත. මම මෙය සොයාගත්තා.

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

මම පයිතන් 2.66 භාවිතා කරමි

මෙය උපකාරී වේ යැයි සිතමි


14
Getattr () ට වඩා මෙය වඩා හොඳ වන්නේ කුමන අංශයෙන්ද?
V13

1
හරියටම මට අවශ්‍ය දේ. චාම් එකක් වගේ වැඩ කරයි! පරිපූර්ණ!! self.__getattribute__('title')සමාන වේself.title
ioaniatr

self.__getattribute__('title')කිසිම අවස්ථාවක ක්‍රියා නොකරයි (ඇයිදැයි නොදනී) දුරින්, නමුත් func = getattr(self, 'title'); func();එසේ කරයි. එබැවින්, getattr()ඒ වෙනුවට භාවිතා කිරීම වඩා හොඳය
ioaniatr

11
පයිතන් නොදන්නා අයට කරුණාකර මෙම කුණු කූඩය නැවැත්විය හැකිද? 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


0

getattrවස්තුවකින් නම අනුව ඇමතුම් ක්‍රමය. නමුත් මෙම වස්තුව ඇමතුම් පන්තියේ මවුපියන් විය යුතුය. මව් පංතිය ලබා ගත හැකියsuper(self.__class__, self)

class Base:
    def call_base(func):
        """This does not work"""
        def new_func(self, *args, **kwargs):
            name = func.__name__
            getattr(super(self.__class__, self), name)(*args, **kwargs)
        return new_func

    def f(self, *args):
        print(f"BASE method invoked.")

    def g(self, *args):
        print(f"BASE method invoked.")

class Inherit(Base):
    @Base.call_base
    def f(self, *args):
        """function body will be ignored by the decorator."""
        pass

    @Base.call_base
    def g(self, *args):
        """function body will be ignored by the decorator."""
        pass

Inherit().f() # The goal is to print "BASE method invoked."

-7

මෙය සරල පිළිතුරකි, උදාහරණයක් ලෙස තිරය ඉවත් කිරීමට මෙය ඔබට ඉඩ සලසයි. පහතින් නිදසුන් දෙකක් ඇත, එවාල් සහ ක්‍රියාත්මක කිරීමෙන් පිරිසිදු කිරීමෙන් පසු ඉහළින් 0 මුද්‍රණය වේ (ඔබ වින්ඩෝස් භාවිතා කරන්නේ නම්, වෙනස් clearකරන්න cls, ලිනක්ස් සහ මැක් භාවිතා කරන්නන් උදාහරණයක් ලෙස පිටව යයි) හෝ පිළිවෙලින් එය ක්‍රියාත්මක කරන්න.

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

3
මෙය ඉල්ලන දේ නොවේ.
Tuncay Göncüoğlu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.