Python 为什么';执行官';函数内部的行为是否不同?

Python 为什么';执行官';函数内部的行为是否不同?,python,python-3.x,list,algorithm,Python,Python 3.x,List,Algorithm,我的问题 我的解决方案: import re import math a = input().replace("|","") op = re.findall("[A-Z]+", a)[0] a = list(map(float,re.split(r'P|S|M|D',a))) expressions = {'P':'str(a[0]+a[1])','S':'str(a[0]-a[1])','M':'str(a[0]*a[1])','D':'str(a[0]/a[1])'} exec('ex =

我的问题

我的解决方案:

import re
import math
a = input().replace("|","")
op = re.findall("[A-Z]+", a)[0]
a = list(map(float,re.split(r'P|S|M|D',a)))
expressions = {'P':'str(a[0]+a[1])','S':'str(a[0]-a[1])','M':'str(a[0]*a[1])','D':'str(a[0]/a[1])'}
exec('ex = eval(expressions[op])+"0"') 
ex = ex[:ex.find(".")+3][::-1]
l = [6]
l.extend([6+3*x for x in range(1,(len(ex)-6)//2+1)])
if ex[-1]=="-":
    l.pop()
for i in l:
    ex = ex[:i] + "|" + ex[i:] 
ex = ex[::-1] 
ex = "0"+ex.strip("|") if ex.find("|")==1 else ex.strip("|")
print(ex)
问题:

import re
import math
a = input().replace("|","")
op = re.findall("[A-Z]+", a)[0]
a = list(map(float,re.split(r'P|S|M|D',a)))
expressions = {'P':'str(a[0]+a[1])','S':'str(a[0]-a[1])','M':'str(a[0]*a[1])','D':'str(a[0]/a[1])'}
exec('ex = eval(expressions[op])+"0"') 
ex = ex[:ex.find(".")+3][::-1]
l = [6]
l.extend([6+3*x for x in range(1,(len(ex)-6)//2+1)])
if ex[-1]=="-":
    l.pop()
for i in l:
    ex = ex[:i] + "|" + ex[i:] 
ex = ex[::-1] 
ex = "0"+ex.strip("|") if ex.find("|")==1 else ex.strip("|")
print(ex)

如果我将此代码包装在接受字符串输入的函数中,并尝试返回我的
ex
,则代码显示错误,并且没有任何更改。我的问题是,有人能解释为什么这一功能单独运行完美,并在封装到函数中时抛出错误吗?

这将在
exec
局部变量的交互中讨论。在
global
上下文(不在函数中)中没有问题-
exec
修改全局变量,您可以看到结果。在函数中,执行上下文是本地函数,但不能更改本地上下文。通常的解决方法是传递一个本地上下文,您可以在其中看到更改:

local_context = {}
exec('ex = eval(expressions[op])+"0"', locals(), local_context)
ex = local_context['ex']
这里,第二个参数
locals()
实际上是作为“globals”传递给exec的。这就是像
表达式
op
这样的东西。在此处传递
globals()
通常没有用处,除非您实际使用的是全局变量或其他函数

第三个参数是本地
exec
可以使用的,以及将填充的内容。如果将
globals()
作为第二个参数传递,那么通常也要传递要在此处使用的局部变量。在此处传递
locals()
不会修改实际的局部变量,因此通常更容易混淆

注释使用

exec('global ex; ex = eval(expressions[op])+"0"')
global ex # Need this to make sure the function knows about the new global variable in its local context
将工作并创建具有正确内容的全局
ex
变量。这就是为什么
exec
像您期望的那样使用函数,在全局上下文中修改当前上下文没有问题。注意,函数本身需要被告知向其本地上下文添加一个全局
ex
,因此需要两个全局变量


请注意,默认情况下,如果没有给出任何值,则局部变量为
locals()
,全局变量为
globals()
,如果只给出全局变量,则局部变量也将等于该值。

为什么不在空格上(字符串)拆分?@klauds。我知道其他的方法,我也能解决它,但我的问题与exec的行为不同。尝试使用
eval
/
exec
解决这个问题是个坏主意。使用实际代码而不是
exec
,更容易、更易于维护,也更容易理解。这将避免您的范围界定问题,并有助于您避免各种“令人惊讶”的行为。@JanChristofterasa我曾试图尽可能减少代码行。在我看来,您似乎在尝试模仿,但由于Python中提供了这些代码,你可以把lambda放到你的
表达式
字典里。我试过
exec('global ex;ex=eval(expressions[op])+“0”)
但是它显示了一个错误,即“变量在定义之前被赋值”@classicdude7啊,我确实没有发布完整的故事
exec
在全局上下文中创建了
ex
,但函数还不知道这一点,因为函数中没有真正调用
global ex
(同样,本地上下文没有更改)。一种解决方案是在
exec
中添加另一个全局变量(如果您愿意),尽管我不太赞成这种解决方案。“我会把它编辑成答案。你能提出一个更好、更简洁的解决方案吗?”classicdude7当然,但最好不要打乱这个QA。问一个新问题,说明您想要什么以及您当前正在做什么(
exec
)。在这里用链接发表评论,我会看一看,虽然知道这个网站在我访问之前你会得到回复。在一行中,可能使用Python内置运算符库(
import operator
),并拥有该库的字典(
operator.add、operator.truediv
等)。可能也不需要
regex