使用自定义名称创建Python动态函数

mah*_*fat 41 python closures metaprogramming dynamic-function python-2.7

如果已经提出并回答了这个问题,请道歉.我需要做的是概念非常简单,但不幸的是我无法在网上找到答案.

我需要在运行时使用自定义名称在Python(Python2.7)中创建动态函数.每个函数的主体也需要在运行时构造,但对于所有函数(几乎)都是相同的.

我从一个名单开始.

func_names = ["func1", "func2", "func3"]
Run Code Online (Sandbox Code Playgroud)

请注意,func_name列表可以包含任意名称列表,因此名称不仅仅是func1,func2,func3,....

我希望结果如下:

    def func1(*args):
        ...

    def func2(*args):
        ...

    def func3(*args):
        ...
Run Code Online (Sandbox Code Playgroud)

我需要这样做的原因是每个函数名称对应一个测试用例,然后从外部世界调用.

更新:没有用户输入.我正在绑一个更大的模块的两端.一端确定测试用例是什么,以及填充测试用例名称的列表.另一端是函数本身,它必须与测试用例的名称进行1:1映射.所以我有测试用例的名称,我知道我想对每个测试用例做什么,我只需要创建具有测试用例名称的函数.由于测试用例的名称是在运行时确定的,因此基于这些测试用例的函数创建也必须在运行时.

更新:我也可以将这个自定义命名函数包装在一个类中,如果这样可以使事情变得更容易.

我可以在字符串中硬编码函数的内容(因为它们几乎相同),或者我可以将它基于先前定义的基类.只需要知道如何用这个内容填充函数.

例如:

    func_content = """
                   for arg in args:
                       print arg
                   """
Run Code Online (Sandbox Code Playgroud)

提前致谢,

马赫迪

Sha*_*way 48

对于你描述的内容,我认为你不需要进入eval或宏 - 通过闭包创建函数实例应该可以正常工作.例:

def bindFunction1(name):
    def func1(*args):
        for arg in args:
            print arg
        return 42 # ...
    func1.__name__ = name
    return func1

def bindFunction2(name):
    def func2(*args):
        for arg in args:
            print arg
        return 2142 # ...
    func2.__name__ = name
    return func2
Run Code Online (Sandbox Code Playgroud)

但是,您可能希望按名称将这些函数添加到某个范围,以便您可以按名称访问它们.

>>> print bindFunction1('neat')
<function neat at 0x00000000629099E8>
>>> print bindFunction2('keen')
<function keen at 0x0000000072C93DD8>
Run Code Online (Sandbox Code Playgroud)


Pau*_*ipp 20

延伸Shane的回答,因为我在寻找类似问题的解决方案时发现了这个问题.注意变量的范围.您可以通过使用生成器函数来定义范围来避免范围问题.这是一个定义类的方法的示例:

class A(object):
    pass

def make_method(name):
    def _method(self):
        print("method {0} in {1}".format(name, self))
    return _method

for name in ('one', 'two', 'three'):
    _method = make_method(name)
    setattr(A, name, _method)
Run Code Online (Sandbox Code Playgroud)

正在使用:

In [4]: o = A()

In [5]: o.one()
method one in <__main__.A object at 0x1c0ac90>

In [6]: o1 = A()

In [7]: o1.one()
method one in <__main__.A object at 0x1c0ad10>

In [8]: o.two()
method two in <__main__.A object at 0x1c0ac90>

In [9]: o1.two()
method two in <__main__.A object at 0x1c0ad10>
Run Code Online (Sandbox Code Playgroud)


Fac*_*ano 7

做这种事情可能有一种反省,但我不认为这是解决这个问题的pythonic方法.

我认为你应该利用python中函数的本质作为一级公民.使用Shane Holloway指出的闭包,可以根据需要自定义功能内容.然后,对于动态名称绑定,使用一个字典,其键是动态定义的名称,值将是函数本身.

def function_builder(args):
    def function(more_args):
       #do stuff based on the values of args
    return function

my_dynamic_functions = {}
my_dynamic_functions[dynamic_name] = function_builder(some_dynamic_args)

#then use it somewhere else
my_dynamic_functions[dynamic_name](the_args)
Run Code Online (Sandbox Code Playgroud)

希望它对你的用例有意义.


Bas*_*tch 3

您可能想使用eval;您将构建包含每个函数的 Python 定义的字符串(即以def func1.... 开头的多行字符串),然后您就eval可以了。

但我会为每个这样的函数生成一个唯一的名称(例如genfun345)。不要对此类名称使用未经检查的用户输入。因为如果该名称与 Python 中的某个已知名称相同,您将陷入难以调试的灾难。

您信任生成这些函数的输入吗?您关心恶意软件或滥用行为吗?

在维基百科上阅读有关卫生宏的信息。