python - 有没有一种方法可以更改 for 循环中的全局函数而不是创建一个新函数?

标签 python global-variables

关于工作代码

当我运行以下代码时,我发现它们按预期工作。

def modify_string(n):
    str1 = ", ".join([f"arg{i}" for i in range(n)])
    str2 = f"func{len(str1.split(', ')) - 1}"\
        f"({', '.join(str1.split(', ')[:-1])})"
    return f"lambda {str1}: list(map(lambda i: list({str2})," \
        f" range({str1.split(', ')[-1]})))"


def create_globals(n):
    global func1
    func1 = lambda x: list(map(lambda j: 0, range(x)))
    for i in range(2, n + 1):
        globals()[f"func{i}"] = eval(modify_string(i)) 


create_globals(3)
print(func3(3, 2, 4))

输出:

[[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]

当调用create_globals(n)函数时,会定义n个不同的函数。函数的名称根据i数字而变化。每个创建的函数都会成为下一步要创建的函数的参数:

在 for 循环的第一步,定义了以下函数:

func2 = lambda arg0, arg1: list(map(lambda i: list(func1(arg0)), range(arg1)))

在 for 循环的第二步,定义了以下函数:

func3 = lambda arg0, arg1, arg2: list(map(lambda i: list(func2(arg0, arg1)), range(arg2)))

所以这是一个创建n 维矩阵的函数。

关于问题

我试图做的是,通过在每个步骤中使用函数的相同全局名称来定义新函数。最后我想使用最后创建的函数。这就是为什么我将代码更改如下:

def modify_string(n):
    str1 = ", ".join([f"arg{i}" for i in range(n)])
    str2 = f"func({', '.join(str1.split(', ')[:-1])})"
    return f"lambda {str1}: list(map(lambda i: list({str2})," \
        f" range({str1.split(', ')[-1]})))"


def create_globals(n):
    global func
    func = lambda x: list(map(lambda j: 0, range(x)))
    for i in range(2, n + 1):
        globals()["func"] = eval(modify_string(i))
        print("func =", modify_string(i))


create_globals(3)

输出:

func = lambda arg0, arg1: list(map(lambda i: list(func(arg0)), range(arg1)))
func = lambda arg0, arg1, arg2: list(map(lambda i: list(func(arg0, arg1)), range(arg2)))

输出看起来符合预期。 但是,当我调用 func(3, 2, 4) 等函数时,我收到 TypeError

func = lambda arg0, arg1: list(map(lambda i: list(func(arg0)), range(arg1)))
func = lambda arg0, arg1, arg2: list(map(lambda i: list(func(arg0, arg1)), range(arg2)))
Traceback (most recent call last):
  File "./a.py", line 21, in <module>
    func(2, 3, 4)
  File "<string>", line 1, in <lambda>
  File "<string>", line 1, in <lambda>
TypeError: <lambda>() missing 1 required positional argument: 'arg2'

即使我已经编写了 arg2,解释器的 react 就好像 arg2 丢失了。您能解释一下为什么会发生这种情况吗?

提前谢谢您。

最佳答案

函数通过在每次访问时查询其globals()来查找非局部变量的非限定名称。 (当然,这就是 def current(): return counter 的工作原理。)因此,您在单个名称下创建的每个函数都引用(在调用时)创建的final函数,而不是任何以前的化身。

构造和执行之间的这种脱节是不生成代码和评估代码的众多原因之一。在这种情况下,为什么不只使用带有可变数量的参数的单个函数,并用它们的前缀调用自身呢?

def mat(*n):
  return [mat(*n[:-1]) for _ in range(n[-1])] if n else 0

关于python - 有没有一种方法可以更改 for 循环中的全局函数而不是创建一个新函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57252863/

相关文章:

php - session 文件 - 它是什么时候创建的?

c++ - 访问数据,BSS段是通过指针还是指令直接寻址?

hadoop - 在reducer中设置并读取驱动程序的Hadoop变量

java - 如何从 Java 的标准输入读取 python 二进制字符串

python 多处理队列 get([block[, timeout]]),阻塞队列中的项目 还是阻塞队列?

python - 使用另一个 DataFrame 创建或修改 DataFrame

Python 类函数无法正常工作

c - extern 与 c 中变量的全局定义

python - 如何在Python中管理全局变量

python - 维护段落计数