具有分配变量的Eval / Exec-Python

时间:2018-06-22 21:04:59

标签: python python-3.x exec eval

以下代码旨在将阶乘转换为其产品。例如。 "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!

1 个答案:

答案 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