简体   繁体   English

如何在 Python 中使用变量作为函数名

[英]How to use a variable as function name in Python

Would it be possible to use a variable as a function name in python?是否可以在python中使用变量作为函数名? For example:例如:

list = [one, two, three]
for item in list:
    def item():
         some_stuff()

Functions in Python are objects that have a name referencing them, so you can pass them around, store in lists and dictionaries (common use when creating jump-tables). Python中的函数是具有引用它们的名称的对象,因此您可以传递它们,存储在列表和字典中(创建跳转表时常用)。

Ie this works: 即这是有效的:

   def one():
        print "1"

    def two():
        print "2"

    def three():
        print "3"

    l = [one, two, three]

    for item in l:
        item()

Will print: 将打印:

1
2
3

Don't use list as variable name, because this way you redefine buildin. 不要使用list作为变量名,因为这样你重新定义了buildin。

def is the statement that is also executed, unlike function defenitions in compiled languages. def是与已编译语言中的函数defenition不同的语句。 So when you call def item(): you don't define function for one , two , three , but redefine item name. 因此,当您调用def item():您没有为onetwothree定义函数,而是重新定义item名称。

In general it is not quite clear what you're trying to do, but it doesn't look like a good idea. 一般来说,你想要做什么并不是很清楚,但它看起来不是一个好主意。 May be explain what you try to accomplish, or rethink the way you want to do it. 可以解释你想要完成什么,或者重新思考你想要的方式。

You can't define a function using a variable but you can rebind the function to the variable name. 您不能使用变量定义函数,但可以将函数重新绑定到变量名称。 Here is an example to add them to the module's global namespace. 下面是将它们添加到模块的全局命名空间的示例。

one = 'one'
two = 'two'
three = 'three'
l = [one, two, three]
def some_stuff():
    print("i am sure some stuff")
for item in l:
    def _f():
        some_stuff()
    globals()[item] = _f
    del _f

one()
two()
three()

Here is a workaround wrapped in a class. 这是一个包含在类中的解决方法。 It uses a dictionary for the mapping: 它使用字典进行映射:

class function_class:
    def __init__(self,fCase):
        fDic = {'A':self.A,         # mapping: string --> variable = function name
                'B':self.B,
                'C':self.C}
        self.fActive = fDic[fCase]
    def A(self): print('here runs function A')
    def B(self): print('here runs function B')
    def C(self): print('here runs function C')
    def run_function(self):
        self.fActive()

#---- main ----------        
fList = ['A','B','C']              # list with the function names as strings
for f in fList:                    # run through the list
    g = function_class(f)
    g.run_function()

The output is: 输出是:

here runs function A
here runs function B
here runs function C

The trick is to use globals(): 诀窍是使用globals():

globals()['use_variable_as_function_name']()

will be equivalent to 将等同于

use_variable_as_function_name()

found at: George Sakkis https://bytes.com/topic/python/answers/792283-calling-variable-function-name 发现于:George Sakkis https://bytes.com/topic/python/answers/792283-calling-variable-function-name


The following is a useful application of the above questioning I needed right now (that's why I came here): apply special functions to URLs depending on their nature: 以下是我现在需要的上述问题的有用应用(这就是我来到这里的原因):根据URL的性质将特殊功能应用于URL:

l = ['condition1', 'condition2', 'condition3']

I used to write 我曾经写过

if 'condition1.' in href:
    return do_something_condition1()
if 'condition2.' in href:
    return do_something_condition2()
if 'condition3.' in href:
    return do_something_condition3()

and so on - my list has 19 members by now and keeps growing. 等等 - 我的名单现在有19名成员并且不断增长。

While investigating the subject and developing, the function code had been quite naturally part of the main function making it soon horrible to read, so relocating the working code into functions was a great relief already. 在研究主题和开发时,功能代码很自然地成为主要功能的一部分,使得阅读很快变得非常糟糕,因此将工作代码重新定位到函数中已经是一个很大的缓解。

This clumsy code above can be substituted by: 上面这个笨拙的代码可以替换为:

for e in l:              # this is my condition list
    if e + '.' in href:  # this is the mechanism to choose the right function
        return globals()['do_something_' + e]()

This way the main code stays simple and legible no matter how long the list of conditions may grow. 这样,无论条件列表可能增长多长时间,主代码都保持简单易读。

Those functions corresponding to the condition labels have to be declared conventionally, of course, depending on the nature of the type of the URL in question: 当然,这些与条件标签对应的函数必须按常规声明,具体取决于所讨论的URL类型的性质:

def do_something_condition1(href):
    # special code 1
    print('========1=======' + href)

def do_something_condition2(href):
    # special code 2
    print('========2=======' + href)

def do_something_condition3(href):
    # special code 3
    print('========3=======' + href)

Test: 测试:

>>> href = 'https://google.com'
>>> for e in l:
...     globals()['do_something_' + e](href)
...
========1=======https://google.com
========2=======https://google.com
========3=======https://google.com

Or, to model it closer to the above scenario: 或者,将其建模为更接近上述场景:

success = '________processed successfully___________ ' 

def do_something_google(href):
    # special code 1
    print('========we do google-specific stuff=======')
    return success + href 

def do_something_bing(href):
    # special code 2
    print('========we do bing-specific stuff=======')
    return success + href 

def do_something_wikipedia(href):
    # special code 3
    print('========we do wikipedia-specific stuff=======')
    return success + href 

Test: 测试:

l = ['google', 'bing', 'wikipedia']

href = 'https://google.com'

def test(href):
    for e in l:
        if e + '.' in href:
            return globals()['do_something_' + e](href)

>>> test(href)
========we do google-specific stuff=======
'________processed successfully___________ https://google.com'

Result: 结果:

Further elaboration on the problem now just amounts to augment the condition list one by one and write the corresponding functions depending on the argument. 现在对问题的进一步阐述只是逐个增加条件列表并根据参数写出相应的函数。 The above mechanism will pick the right one thereafter. 以上机制将选择正确的机制。

The short answer is no. 最简洁的答案是不。 When you declare a variable, you have bound a name to an object. 声明变量时,已将名称绑定到对象。 The same is true when you declare a function. 声明函数时也是如此。 You can try it out for yourself in a python console and see what happens: 你可以在python控制台中自己试试看看会发生什么:

>name=1
>name
1
>def name(x): print(x+1)

>name
function name at 0x000001CE8B8122F0

You can do this: 你可以这样做:

from types import FunctionType
from copy import copy

def copy_function(fn):
    return FunctionType(copy(fn.func_code), copy(fn.func_globals), name=item,
                        argdefs=copy(fn.func_defaults),
                        closure=copy(fn.func_closure))

list = ['one', 'two', 'three']

for item in list:
    def _fn():
        print(item)
    globals()[item] = copy_function(_fn)
list = map(eval, list)

Here is an updated answer from @enrico.basis:这是来自@enrico.basis 的更新答案:

from types import FunctionType
from copy import copy


def copy_function(fn):
    return FunctionType(
        code=copy(fn.__code__),
        globals=copy(fn.__globals__),
        name=fn.__name__,
        argdefs=copy(fn.__defaults__),
        closure=copy(fn.__closure__)
    )


items = ['print_one', 'print_two', 'print_three']

for ele in items:
    def _f():
        return 'String from {}() function'.format(ele)
    _f.__name__ = ele
    locals()[ele] = copy_function(_f)
    del _f


for ele in items:
    _f = eval(ele)
    print('- {}'.format(_f()))

This will give the following output:这将提供以下输出:

- String from print_one() function
- String from print_two() function
- String from print_three() function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM