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']