带有赋值变量的Eval/Exec-Python [英] Eval/Exec with assigning variable - Python

查看:90
本文介绍了带有赋值变量的Eval/Exec-Python的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码旨在将阶乘转换为其产品.例如. "4!"-> "(4*3*2*1)".由于行exec(codeToRun),此代码不起作用.但是,如果我改为将codeToRun的值替换为exec(codeToRun),则它可以正常工作,那么exec为什么不起作用?

The below piece of code is aimed at converting a factorial into its products. E.g. "4!" --> "(4*3*2*1)". This code does not work due to the line exec(codeToRun). However, if I instead put the value of codeToRun in place of exec(codeToRun) then it works perfectly so why doesn't exec work?

不工作↓

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 阶乘的数量可以大于一个,每个阶乘的位数也可以大于一个.

EDIT #1 The number of factorials can be more than one and the number of digits in each factorial can be more than one as well.

输入:"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!.

EDIT #2 I have added a print statement outputting the string as seen in the two pieces of code. Now when I run the program and enter 4!, the program pauses (as if it was an infinite loop). I then press CTRL+C to exit the program and it decides to output 4!. This then happens every time I press CTRL+C so the line must be running because the print statement occurs but it remains at 4!.

推荐答案

让我们快速浏览一下文档:

Let's have a quick look at the docs:

有关模块内置模块中内置函数exec的帮助:

Help on built-in function exec in module builtins:

exec(source,globals = None,locals = None,/) 在全局变量和局部变量的上下文中执行给定的源.

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() 返回包含当前范围的局部变量的字典.

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.

最后的注释似乎可以解释您的麻烦.

This final note would appear to explain your troubles.

更具体地说,您正在使用一个参数调用exec,因此它将在globals()之上的locals()的默认环境中执行.重要的是要意识到,这些不一定与实际的全球范围和局部范围相同,但理论上可以是代理或副本或任何其他形式.现在,例如,如果您分配一个变量,则这些字典之一将相应地更新. locals 文档中的注释说的是,不能保证此更新将传播到实际的本地范围.我认为这就是为什么您的程序无法正常工作的原因.

To be more specific, you are calling exec with one parameter, so it will execute in the default environment of locals() on top of globals(). It is important to realize, that these are not necessarily identical with the actual global and local scopes, but may in theory be proxies or copies or whatever. Now, if you, for example, assign a variable one of these dictionaries gets updated accordingly. What the note in the docs for locals says, is that there is no guarantee that this update will be propagated to the actual local scope. And this I think is why your program doesn't work.

如何解决此问题:

基于上述一个简单的解决方法是

Based on the above one easy fix is

(1)与您自己订立合同,将codeToRun分配给stringToCheck.

(1) make a contract with yourself that codeToRun assigns to stringToCheck.

(2)保留对您传递给exec

(2) keep a reference to the instance of locals() you pass to exec

(3)使用它来显式设置stringToCheck

(3) use this to explicitly set stringToCheck

所以您的except块看起来有点像

So your except block would look somewhat like

    l = locals()
    exec(codeToRun, globals(), l)
    stringToCheck = l['stringToCheck']

这篇关于带有赋值变量的Eval/Exec-Python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆