有没有办法更改 for 循环中的全局函数而不是创建一个新函数?



关于工作代码

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

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,口译员的反应就好像arg2不见了一样。你能解释一下为什么会这样吗?

提前谢谢你。

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

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

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

相关内容

  • 没有找到相关文章

最新更新