以下代码旨在将阶乘转换为其产品。例如。 "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 阶乘的数量可以大于一个,每个阶乘的位数也可以大于一个。
输入:
"11!/10!"
预期输出:
"(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
时都会发生这种情况,因此该行必须正在运行,因为出现了print语句,但它仍位于4!
。
答案 0 :(得分:1)
让我们快速浏览一下文档:
有关模块内置模块中内置函数exec的帮助:
exec(source,globals = None,locals = None,/) 在全局变量和局部变量的上下文中执行给定的源。
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.
和
有关内置模块内置函数的本地帮助:
locals() 返回包含当前范围的局部变量的字典。
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)保留对您传递给locals()
的{{1}}实例的引用
(3)使用它来显式设置exec
所以您的stringToCheck
块看起来有点像
except