加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 修改函数参数

发布时间:2020-12-20 12:34:21 所属栏目:Python 来源:网络整理
导读:对不起,如果这是一个愚蠢的问题,但我已经找了一段时间,但没有真正找到答案. 如果我正在编写python函数,例如: def function(in1,in2): in1=in1+1 in2=in2+1 如何使这些更改坚持下去? 我知道他们为什么不这样做,这已在许多答案中得到解决,但我找不到如何让他
对不起,如果这是一个愚蠢的问题,但我已经找了一段时间,但没有真正找到答案.

如果我正在编写python函数,例如:

def function(in1,in2):
    in1=in1+1
    in2=in2+1

如何使这些更改坚持下去?

我知道他们为什么不这样做,这已在许多答案中得到解决,但我找不到如何让他们这样做的问题的答案.如果没有返回值或创建某种类,那么函数是否真的无法在全局意义上对其参数进行操作?

我也希望这些变量本身不是全局的,因为我希望能够这样做:

a=1
b=2
c=3
d=4
function(a,b)
function(c,d)

这只是一厢情愿的想法吗?

解决方法

它可以做但我警告你 – 它不会很漂亮!你可以做的是捕获你的函数中的调用者框架,然后拿起调用行,解析它并提取传递的参数,然后将它们与你的函数签名进行比较并创建一个参数图,然后调用你的函数和你的函数完成比较本地堆栈中的更改并使用映射的更改更新调用方框架.如果你想看看它有多愚蠢,这里是一个演示:

# 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

现在,您可以轻松地修饰您的功能,使其能够执行这种不敬虔的讽刺:

# 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)

显然,这仅适用于具有位置参数的非嵌套函数,并且只有当您传递简单的本地参数时,才可以自由地处理关键字参数,不同堆栈,返回/包装/链接调用以及其他恶作剧的漏洞.如果这就是你想要的.

或者,您知道,您可以使用为此发明的结构,如全局变量,类,甚至是封闭的可变对象.并停止谋杀小精灵.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读