修改函数参数 [英] Modifying function arguments
问题描述
对不起,如果这是一个愚蠢的问题,但我已经找了一段时间并没有真正找到答案.
Sorry if this is a dumb question, but I've looked for a while and not really found the answer.
如果我正在编写一个python函数,例如:
If I'm writing a python function, for example:
def function(in1, in2):
in1=in1+1
in2=in2+1
如何使这些更改坚持下去?
How do I make these changes stick?
我知道他们为什么不这样做,这已经在许多答案中得到解决,但我找不到如何真正让他们这样做的问题的答案.如果不返回值或创建某种类,函数是否真的无法在全局意义上对其参数进行操作?
I know why they dont, this has been addressed in many answers, but I couldn't find an answer to the question of how to actually make them do so. Without returning values or making some sort of class, is there really no way for a function to operate on its arguments in a global sense?
我也希望这些变量本身不是全局变量,因为我希望能够做到这一点:
I also want these variables to not be global themselves, as in I want to be able to do this:
a=1
b=2
c=3
d=4
function(a,b)
function(c,d)
这只是一厢情愿吗?
推荐答案
它可以做到,但我警告你 - 它不会很漂亮!您可以做的是在您的函数中捕获调用者框架,然后拿起调用行,解析它并提取传递的参数,然后将它们与您的函数签名进行比较并创建一个参数映射,然后调用您的函数并调用一次您的函数完成比较本地堆栈中的更改并使用映射的更改更新调用者帧.如果你想看看它会变得多么愚蠢,这里有一个演示:
It can be done but I'm warning you - it won't be pretty! What you can do is to capture the caller frame in your function, then pick up the call line, parse it and extract the arguments passed, then compare them with your function signature and create an argument map, then call your function and once your function finishes compare the changes in the local stack and update the caller frame with the mapped changes. If you want to see how silly it can get, here's a demonstration:
# HERE BE DRAGONS
# No, really, here be dragons, this is strictly for demonstration purposes!!!
# Whenever you use this in code a sweet little pixie is brutally killed!
import ast
import inspect
import sys
def here_be_dragons(funct): # create a decorator so we can, hm, enhance 'any' function
def wrapper(*args, **kwargs):
caller = inspect.getouterframes(inspect.currentframe())[1] # pick up the caller
parsed = ast.parse(caller[4][0], mode="single") # parse the calling line
arg_map = {} # a map for our tracked args to establish global <=> local link
for node in ast.walk(parsed): # traverse the parsed code...
# and look for a call to our wrapped function
if isinstance(node, ast.Call) and node.func.id == funct.__name__:
# loop through all positional arguments of the wrapped function
for pos, var in enumerate(funct.func_code.co_varnames):
try: # and try to find them in the captured call
if isinstance(node.args[pos], ast.Name): # named argument!
arg_map[var] = node.args[pos].id # add to our map
except IndexError:
break # no more passed arguments
break # no need for further walking through the ast tree
def trace(frame, evt, arg): # a function to capture the wrapped locals
if evt == "return": # we're only interested in our function return
for arg in arg_map: # time to update our caller frame
caller[0].f_locals[arg_map[arg]] = frame.f_locals.get(arg, None)
profile = sys.getprofile() # in case something else is doing profiling
sys.setprofile(trace) # turn on profiling of the wrapped function
try:
return funct(*args, **kwargs)
finally:
sys.setprofile(profile) # reset our profiling
return wrapper
现在您可以轻松地装饰您的函数,使其能够执行这种不敬虔的讽刺:
And now you can easily decorate your function to enable it to perform this ungodly travesty:
# Zap, there goes a pixie... Poor, poor, pixie. It will be missed.
@here_be_dragons
def your_function(in1, in2):
in1 = in1 + 1
in2 = in2 + 1
现在,演示:
a = 1
b = 2
c = 3
d = 4
# Now is the time to play and sing along: Queen - A Kind Of Magic...
your_function(a, b) # bam, two pixies down... don't you have mercy?
your_function(c, d) # now you're turning into a serial pixie killer...
print(a, b, c, d) # Woooo! You made it! At the expense of only three pixie lives. Savage!
# prints: (2, 3, 4, 5)
显然,这仅适用于具有位置参数的非嵌套函数,并且仅当您传递简单的本地参数时,才可以随意进入处理关键字参数、不同堆栈、返回/包装/链接调用的兔子洞,和其他恶作剧,如果那是你喜欢的.
This, obviously, works only for non-nested functions with positional arguments, and only if you pass simple local arguments, feel free to go down the rabbit hole of handling keyword arguments, different stacks, returned/wrapped/chained calls, and other shenanigans if that's what you fancy.
或者,您知道,您可以使用为此发明的结构,例如全局变量、类,甚至封闭的可变对象.并停止谋杀小精灵.
Or, you know, you can use structures invented for this, like globals, classes, or even enclosed mutable objects. And stop murdering pixies.
这篇关于修改函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!