Eval/Exec 分配变量 - Python
Eval/Exec with assigning variable - Python
下面的一段代码旨在将阶乘转换为其乘积。例如。 "4!"
--> "(4*3*2*1)"
。由于行 exec(codeToRun)
,此代码不起作用。但是,如果我改为将 codeToRun
的值代替 exec(codeToRun)
那么它就可以完美地工作,那么为什么 exec
不起作用?
不行↓
def checkSpecialChars(char, stringToCheck, codeToRun):
while char in stringToCheck:
currentString=""
for i in range(len(stringToCheck)):
if stringToCheck[i]==char:
try:
eval(codeToRun)
except:
exec(codeToRun)
print(stringToCheck)
currentString=""
break
if stringToCheck[i].isdigit():
currentString+=stringToCheck[i]
else:
currentString=""
return stringToCheck
有效↓
def checkSpecialChars(char, stringToCheck, codeToRun):
while char in stringToCheck:
currentString=""
for i in range(len(stringToCheck)):
if stringToCheck[i]==char:
try:
eval(codeToRun)
except:
stringToCheck = stringToCheck[:i-len(currentString)] + "(" + "*".join(str(integer) for integer in range(int(currentString),0,-1)) + ")" + stringToCheck[i+1:]
print(stringToCheck)
currentString=""
break
if stringToCheck[i].isdigit():
currentString+=stringToCheck[i]
else:
currentString=""
return stringToCheck
编辑#1
阶乘的个数可以大于1,每个阶乘的位数也可以大于1
Input: "11!/10!"
Expected Output: "(11*10*9*8*7*6*5*4*3*2*1)/(10*9*8*7*6*5*4*3*2*1)"
编辑#2
我添加了一个输出字符串的打印语句,如两段代码所示。现在,当我 运行 程序并输入 4!
时,程序暂停(好像是一个无限循环)。然后我按 CTRL+C
退出程序,它决定输出 4!
。每次我按 CTRL+C
时都会发生这种情况,所以该行必须是 运行ning 因为打印语句出现但它仍然在 4!
.
让我们快速浏览一下文档:
Help on built-in function exec in module builtins:
exec(source, globals=None, locals=None, /)
Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
和
Help on built-in function locals in module builtins:
locals()
Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.
最后的注释似乎可以解释您的问题。
更具体地说,您使用一个参数调用 exec,因此它将在 globals() 之上的 locals() 的默认环境中执行。重要的是要认识到,这些不一定与实际的全局和本地范围相同,但理论上可能是代理或副本或其他任何东西。现在,例如,如果您分配一个变量,这些词典中的一个就会相应地更新。 locals 的文档中的说明是,不能保证此更新将传播到实际的本地范围。我认为这就是您的程序无法运行的原因。
如何解决这个问题:
基于以上一个简单的修复是
(1) 与自己签订合同,codeToRun
分配给 stringToCheck
。
(2) 保留对您传递给 exec
的 locals()
实例的引用
(3) 使用它来显式设置 stringToCheck
所以你的 except
块看起来有点像
l = locals()
exec(codeToRun, globals(), l)
stringToCheck = l['stringToCheck']
下面的一段代码旨在将阶乘转换为其乘积。例如。 "4!"
--> "(4*3*2*1)"
。由于行 exec(codeToRun)
,此代码不起作用。但是,如果我改为将 codeToRun
的值代替 exec(codeToRun)
那么它就可以完美地工作,那么为什么 exec
不起作用?
不行↓
def checkSpecialChars(char, stringToCheck, codeToRun):
while char in stringToCheck:
currentString=""
for i in range(len(stringToCheck)):
if stringToCheck[i]==char:
try:
eval(codeToRun)
except:
exec(codeToRun)
print(stringToCheck)
currentString=""
break
if stringToCheck[i].isdigit():
currentString+=stringToCheck[i]
else:
currentString=""
return stringToCheck
有效↓
def checkSpecialChars(char, stringToCheck, codeToRun):
while char in stringToCheck:
currentString=""
for i in range(len(stringToCheck)):
if stringToCheck[i]==char:
try:
eval(codeToRun)
except:
stringToCheck = stringToCheck[:i-len(currentString)] + "(" + "*".join(str(integer) for integer in range(int(currentString),0,-1)) + ")" + stringToCheck[i+1:]
print(stringToCheck)
currentString=""
break
if stringToCheck[i].isdigit():
currentString+=stringToCheck[i]
else:
currentString=""
return stringToCheck
编辑#1 阶乘的个数可以大于1,每个阶乘的位数也可以大于1
Input:
"11!/10!"
Expected Output:
"(11*10*9*8*7*6*5*4*3*2*1)/(10*9*8*7*6*5*4*3*2*1)"
编辑#2
我添加了一个输出字符串的打印语句,如两段代码所示。现在,当我 运行 程序并输入 4!
时,程序暂停(好像是一个无限循环)。然后我按 CTRL+C
退出程序,它决定输出 4!
。每次我按 CTRL+C
时都会发生这种情况,所以该行必须是 运行ning 因为打印语句出现但它仍然在 4!
.
让我们快速浏览一下文档:
Help on built-in function exec in module builtins:
exec(source, globals=None, locals=None, /) Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements or a code object as returned by compile(). The globals must be a dictionary and locals can be any mapping, defaulting to the current globals and locals. If only globals is given, locals defaults to it.
和
Help on built-in function locals in module builtins:
locals() Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in the local scope and vice-versa is *implementation dependent* and not covered by any backwards compatibility guarantees.
最后的注释似乎可以解释您的问题。
更具体地说,您使用一个参数调用 exec,因此它将在 globals() 之上的 locals() 的默认环境中执行。重要的是要认识到,这些不一定与实际的全局和本地范围相同,但理论上可能是代理或副本或其他任何东西。现在,例如,如果您分配一个变量,这些词典中的一个就会相应地更新。 locals 的文档中的说明是,不能保证此更新将传播到实际的本地范围。我认为这就是您的程序无法运行的原因。
如何解决这个问题:
基于以上一个简单的修复是
(1) 与自己签订合同,codeToRun
分配给 stringToCheck
。
(2) 保留对您传递给 exec
locals()
实例的引用
(3) 使用它来显式设置 stringToCheck
所以你的 except
块看起来有点像
l = locals()
exec(codeToRun, globals(), l)
stringToCheck = l['stringToCheck']