【问题标题】:How to dynamically create a python function within a module?如何在模块中动态创建 python 函数?
【发布时间】:2021-08-11 16:55:45
【问题描述】:

我写了一个函数def_function,它在运行时动态定义了另一个函数。

ma​​in.py

#!/usr/bin/python3

def def_function(name):
  lines = list()
  lines.append('global {}\n'.format(name))
  lines.append('def {}():\n'.format(name))
  lines.append('  print(\'{}() has been called!\')\n'.format(name))
  code = ''.join(lines)
  function = compile(code, '', 'exec')
  exec(function)

def_function('foo')
foo()

运行 ma​​in.py 给出预期的输出:

foo() 已被调用!

现在我想将def_function 的定义移动到module.py 并从main.py 导入。

module.py

def def_function(name):
  lines = list()
  lines.append('global {}\n'.format(name))
  lines.append('def {}():\n'.format(name))
  lines.append('  print(\'{}() has been called!\')\n'.format(name))
  code = ''.join(lines)
  function = compile(code, '', 'exec')
  exec(function)

ma​​in.py

#!/usr/bin/python3

from module import def_function

def_function('foo')
foo()

这会导致以下错误:

Traceback (most recent call last):
  File "./main.py", line 6, in <module>
    foo()
NameError: name 'foo' is not defined

我已经在 SO 上搜索了我的问题并阅读了各种问题,但我找不到解决方案。请帮帮我。

【问题讨论】:

  • 你知道你可以在 Python 中编写嵌套函数定义吗?
  • 我知道,但据我了解嵌套函数的代码无法在运行时生成。我的真实函数根据def_function 的进一步参数生成代码。
  • 所有 Python 中的函数都是在运行时创建的! (除了没有用def ...写的内置的)

标签: python-3.x function import exec


【解决方案1】:

您在module.py 范围内定义foo。不要忘记导入module.py

致电foo(),使用module.foo()

import module

module.def_function('foo')
module.foo()

可以帮助你https://realpython.com/python-scope-legb-rule/

附加

exec(function) 之后添加这个。同时导入sys

setattr(sys.modules['__main__'], name, globals()[name])

Setattr 函数将值分配给对象的属性或创建新属性。 https://docs.python.org/3/library/functions.html#setattr

module.py

import sys


def def_function(name):
    lines = list()
    lines.append('global {}\n'.format(name))
    lines.append('def {}():\n'.format(name))
    lines.append('  print(\'{}() has been called!\')\n'.format(name))
    code = ''.join(lines)
    function = compile(code, '', 'exec')
    exec(function)
    setattr(sys.modules['__main__'], name, globals()[name])

ma​​in.py

from module import def_function

def_function('foo')
foo()

【讨论】:

  • 感谢您提供可能的解决方法/解决方案。有没有办法在 module.py 内的全局范围内定义 foo
  • @DnsLnk 是的,你可以。
  • 老实说,还有其他方法可以解决这个问题,但需要更多上下文。
  • 感谢您提供更多信息!这正是我一直在寻找的。只要我有足够的声誉,我就会支持你的回答。 :)
【解决方案2】:

你的例子可以这样写,有一个嵌套的函数定义,没有compileexec

def def_function(name):
    def f():
        print(name, "has been called")
    return f

# ...

foo = def_function("foo")

但是,您必须退回它。

【讨论】:

  • 谢谢,但如果我在运行前知道foo 的代码,那么我会像定义任何其他函数一样定义它。我真正的def_function 包含各种ifs、elses 和循环并根据进一步的参数生成foo。我认为这不能通过嵌套函数定义来完成。不过我可能错了。
猜你喜欢
  • 2017-11-21
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-25
  • 2011-03-28
  • 2013-07-18
相关资源
最近更新 更多