Python-修改传递给函数的变量
如果我有一个函数Python-修改传递给函数的变量,python,reference,in-place,Python,Reference,In Place,如果我有一个函数f(x)和任何类型和范围的变量var,有没有办法修改var对f(var)的内部调用 这意味着函数f做了一些神奇的事情来获得对原始var的引用(如C++中的引用/指针),并修改原始var,用于任何类型的var(甚至int//code>float/str/字节) 不允许将var包装到dict或list或任何其他类中。因为大家都知道dict/list是通过引用传递的 也不允许从函数返回新值以重新分配变量 也不允许修改原始变量的范围(如使其成为全局变量) 事实上,不允许对函数调用方的代码
f(x)
和任何类型和范围的变量var
,有没有办法修改var
对f(var)
的内部调用
这意味着函数f
做了一些神奇的事情来获得对原始var
的引用(如C++
中的引用/指针),并修改原始var
,用于任何类型的var
(甚至int
//code>float/str
/字节
)
不允许将var
包装到dict
或list
或任何其他类中。因为大家都知道dict/list是通过引用传递的
也不允许从函数返回新值以重新分配变量
也不允许修改原始变量的范围(如使其成为全局变量)
事实上,不允许对函数调用方的代码进行任何更改
该变量可以是任何想象的类型和范围,不应对其进行任何假设
这样下一个代码就可以工作了(这样的代码既可以放在另一个包装函数中,也可以放在全局范围内,这无关紧要):
如果需要解决任务,此函数可以执行任何复杂操作,如使用inspect
模块
基本上,我需要以某种方式打破关于简单类型通过值传递的约定,即使是以某种非简单/神秘的方式实现这一点
我很确定这个任务可以通过标准逆向工程模块(如//)中的工具来解决
为了澄清我对这项任务的需求——目前,对于这项任务,我并没有尝试使用整洁的Python风格和方法来很好地编写代码,您可以想象,这项任务在未来是专门从事逆向工程/抗病毒药物/代码安全性/编译器实现的公司的面试问题。类似这样的任务还可以探索Python等语言的所有隐藏可能性。正如@rcvaram所建议的那样,使用全局变量,如下所示
def magic_inplace_add(x, val):
global var
var = 333
global var
var = 111
magic_inplace_add(var, 222) # modifies int var by adding 222
print(var)
对于模块范围变量
import inspect
import re
def magic_inplace_add(var, val):
'''
Illustation of updating reference to var when function is called at module level (i.e. not nested)
'''
# Use inspect to get funcstion call syntax
previous_frame = inspect.currentframe().f_back
(filename, line_number,
function_name, lines, index) = inspect.getframeinfo(previous_frame)
# lines contains call syntax
# i.e. ['magic_inplace_add(x, 222)\n']
args = re.findall("\w+", lines[0]) # get arguments of calling syntax i.e. ('magic_inplace_add', 'x', 222)
# Update variable in context of previous frame
# i.e. args[1] == 'x' in example
if args[1] in previous_frame.f_globals:
# update variable from global
previous_frame.f_globals.update({args[1]:var + val})
elif args[1] in previous_frame.f_locals:
# for nested function variable would be in f_locals
# but this doesn't work in Python 3 this f_locals is a copy of actual locals in calling frame
# see Martijn Pieters answer at
# https://stackoverflow.com/questions/36678241/how-can-i-force-update-the-python-locals-dictionary-of-a-different-stack-frame
previous_frame.f_locals.update({args[1]:var + val}) # this is what would be used for nested functions
示例
x = 111 # x module scope
y = 222 # y module scope
z = 333 # z module scope
magic_inplace_add(x, 222)
magic_inplace_add(y, 222)
magic_inplace_add(z, 222)
print(x) # Output: 333
print(y) # Output: 444
print(z) # Output: 555
使用全局variables@rcvaram事实上,不允许以任何方式更改函数调用代码。您是否真的需要打破Python的基本规则,即不可变变量不能以这种方式修改?“已知dict/list是通过引用传递的”不知道,因为这是错误的。Python从不经过任何东西reference@Arty这根本不能回答我的问题。您所要求的并不是完全指定的,您不断地对Python的语义做出错误的陈述,试图解释您想要做什么,这使得它更加混乱。如果你想做一些非常粗糙的事情,那么你需要能够准确地解释你想做什么。我在我的问题中说过,不允许更改变量的类型或范围。事实上,不允许对函数的调用方代码进行任何修改。谢谢!向上投票。当测试代码在全局范围内时,至少对我有效。但奇怪的是,当测试代码在一个函数中不起作用时,局部变量dict不会改变,尽管magic func在模块级,@Arty——不奇怪——这是我对嵌套函数(即在另一个函数中)时不起作用的评论。问题是elif分支更新局部变量,而不是Python 3中的实际局部变量,正如我提供的链接所证明的那样。@DarryIG我认为您所说的func应该在模块/全局范围内,但正如我在前面的评论中对代码的链接一样,变量似乎也应该在模块/全局范围内?所以函数和变量都应该在全局范围内——这是代码运行的先决条件吗?但仍然是非常好的,至少有一个工作的解决方案已经张贴,我投了你的解决方案@顺便问一下,Python不允许修改前一帧的局部变量的原因是什么?是出于安全原因,防止我们做我们打算做的事情还是出于其他原因?@Arty——似乎这本可以在Python 2中使用,但Python 3的性能优化改变了行为,即。
x = 111 # x module scope
y = 222 # y module scope
z = 333 # z module scope
magic_inplace_add(x, 222)
magic_inplace_add(y, 222)
magic_inplace_add(z, 222)
print(x) # Output: 333
print(y) # Output: 444
print(z) # Output: 555