【发布时间】:2019-12-09 16:12:49
【问题描述】:
所以我需要在一个大型函数中进行一些重复的操作。啊哈!嵌套函数来救援!哦,但是大多数重复都涉及到对函数中局部变量的修改!啊哈!非本地的救援!但是,非本地语句几乎与嵌套函数内容一样多。我真正需要的是一个宏?
嗯。 nonlocal * (意味着所有变量都是非本地引用)会很好,然后嵌套函数可以将其所有引用都指向外部范围......但这不会仅限于外部范围,这可能会很糟糕一种通用技术。哦,是的,而且非本地 * 不存在。
怎么办?唔。代替def,编译()一些代码,稍后再执行()呢?
nestedfunc = compile("some code", "nestedfunc", "exec")
那么以后
exec( nestedfunc )
但是文档中的这个注释呢?
注意:默认局部变量的作用与以下函数 locals() 的描述相同: 不应该修改默认的本地字典 尝试过。如果您需要查看,请传递明确的本地字典 函数 exec() 返回后代码对本地人的影响。
“一些代码”确实想修改当前范围内的局部变量。这行得通吗?
不,即使是像某些代码这样的简单案例
y=y+1
证明警告的有效性:y 在以后的使用中保持不变。
嗯。如果外部函数也是一块已编译的代码,并且将本地函数传递给它怎么办?这似乎适用于粗略测试,每次从编译的外部函数调用嵌套函数时,y 的值都会增加。
a_global = 10
outer_func = compile('''
print( f'{a_global}, {y}')
exec( nested_func )
print( f'{a_global}, {y}')
exec( nested_func )
print( f'{a_global}, {y}')
exec( nested_func )
print( f'{a_global}, {y}')
exec( nested_func )
print( f'{a_global}, {y}')
''', 'outer_func', 'exec')
nested_func = compile('''
global a_global
a_global += 10
y += 1
''', 'nested_func', 'exec')
locs = {'y': 1 }
exec( outer_func, globals(), locs )
exec( outer_func, globals(), locs )
exec( outer_func, globals(), locs )
结果:
10, 1
20, 2
30, 3
40, 4
50, 5
50, 5
60, 6
70, 7
80, 8
90, 9
90, 9
100, 10
110, 11
120, 12
130, 13
所以这段代码似乎满足了要求:nested_func 可以引用和更新outer_func 中的局部变量,而不需要nonlocal 或nonlocal *,不能(除非使用nonlocal 或global)访问其他外部作用域中的变量,并且只定义在一个持续更新的地方。
不过确实很丑。有没有人看到任何漏洞,或者有更好的解决方案?
【问题讨论】:
-
一个好的解决方案首先不使用全局变量。
-
这太丑了。很难理解你试图达到的目标。如果您需要以某种方式保留函数的内部状态以供以后调用,请将 dict 中的本地变量返回到外部并再次将它们传回。
-
@Jean-FrançoisFabre 使用全局变量只是为了演示在nested_func 中使用全局变量或非局部变量(如果需要)的可能性,而不是建议使用全局变量。我正在探索这里的操作方法。
-
@PatrickArtner 目标是避免在大型函数中的不同位置重复出现相同代码块。这个例子不是特别有趣,只是展示了一个丑陋的技术来达到目的。代替 y += 1,替换为 2-5 行代码块,该代码块依赖并更改函数中的本地状态。代替对nested_func 的简单顺序调用,添加周围的条件逻辑。该示例只是提炼出试图避免代码重复的问题/解决方案。
标签: python-3.x