简体   繁体   中英

why 'exec' is behaving different inside the function?

My Question

问题

My solution:

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)

The issue:

If I wrap this code inside a function who take string input and try to return my ex the code shows error and nothing is changed.My question is, can anyone explain why this works perfect alone and throws error when wrapped inside a function?

This is discussed on exec s interaction with locals . In the global context (not in a function) there is no problem - exec modifies global variables, and you see the result. In a function the execution context is the local function, but exec cannot change the local context . The usual work around is to pass a local context where you can see the changes:

local_context = {}
exec('ex = eval(expressions[op])+"0"', locals(), local_context)
ex = local_context['ex']

Here, the second parameter locals() is in fact passed as a "globals" to exec. This is so stuff like expressions and op are available. Passing globals() here is usually not useful unless you are actually using a global variable or some other function.

The third parameter is the locals exec can use, and what will be populated. If you pass globals() as the second parameter, then usually you want to pass local variables you intend to use here as well. Passing locals() here will not modify your actual locals, so is usually more confusing.

Note using

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

will work and create a global ex variable with the correct content. This is why exec works out of a function as you expect, in the global context there is no problem in modifying the current context. Note the function itself needs to be told to add a global ex to its local context, hence two globals.

Note the defaults is for the locals to be locals() and globals to be globals() if nothing is given, and if only the globals are given then the locals will equal that as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM