如何在Python中获取/设置函数的局部变量(从外部)?

14 投票
5 回答
20073 浏览
提问于 2025-04-15 13:59

如果我有一个这样的函数(在Python 2.5.2中):

def sample_func():
    a = 78
    b = range(5)
    #c = a + b[2] - x

我的问题是:

  1. 如何在外部获取这个函数的局部变量(a, b),而使用函数内部的locals()?(有点像反射)
  2. 有没有办法从外部设置一个局部变量(比如x

提前谢谢大家。

编辑

大家都在问用例,但这是个奇怪的情况。(别怪我,我不是创造这个的)。以下是场景:

  1. 我有一个加密的Python源文件,里面包含一个Python函数。
  2. 一个C扩展模块解密这个文件,并在内存中构建那个函数。
  3. 一个主Python程序首先调用C扩展,传入那个加密文件的位置。
  4. 然后主程序调用在内存中构建的函数(由C扩展构建)
  5. 但是主程序需要知道那个函数的局部变量(别问我为什么,这不是我做的)
  6. 出于某种(真是)奇怪的原因,主程序还需要设置一个变量(这是最奇怪的)。

5 个回答

3

我不太确定这是不是你想要的意思,但在Python中,函数也是一种对象,你可以把变量绑定到一个函数对象上,然后从“外部”访问这些变量:

def fa():
    print 'x value of fa() when entering fa(): %s' % fa.x
    print 'y value of fb() when entering fa(): %s' % fb.y
    fa.x += fb.y
    print 'x value of fa() after calculation in fa(): %s' % fa.x
    print 'y value of fb() after calculation in fa(): %s' % fb.y
    fa.count +=1


def fb():
    print 'y value of fb() when entering fb(): %s' % fb.y
    print 'x value of fa() when entering fa(): %s' % fa.x
    fb.y += fa.x
    print 'y value of fb() after calculation in fb(): %s' % fb.y
    print 'x value of fa() after calculation in fb(): %s' % fa.x
    print 'From fb() is see fa() has been called %s times' % fa.count


fa.x,fb.y,fa.count = 1,1,1

for i in range(10):
    fa()
    fb()

如果我说错了,请多多包涵……我自己也是Python和编程的初学者……

9

我不太清楚你具体想做什么,但把它做成一个类可能会更好。你可以定义一个叫做 __call__ 的方法,这样这个类就可以像函数一样使用。

比如:

>>> class sample_func(object):
...     def __init__(self):
...         self.a = 78
...         self.b = range(5)
...     def __call__(self):
...         print self.a, self.b, self.x
... 
>>> f = sample_func()
>>> print f.a
78
>>> f.x = 3
>>> f()
78 [0, 1, 2, 3, 4] 3

(这个例子是基于你给的简单示例,所以代码可能不是很有意义。如果你能提供更多细节,我们可能能给出更好的建议。)

19

不可以。一个没有被执行的函数是没有局部变量的,它只是一个函数。问如何修改一个没有运行的函数的局部变量,就像问如何在程序没有运行时修改它的堆内存一样。

不过,如果你真的想的话,可以修改常量。

def func():
    a = 10
    print a

co = func.func_code
modified_consts = list(co.co_consts)
for idx, val in enumerate(modified_consts):
    if modified_consts[idx] == 10: modified_consts[idx] = 15

modified_consts = tuple(modified_consts)

import types
modified_code = types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, modified_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab)
modified_func = types.FunctionType(modified_code, func.func_globals)
# 15:
modified_func()

这是一种技巧,因为我们无法知道co.co_consts中的每个常量具体是什么;这个方法使用了一个特殊值来帮助识别。根据你的使用情况是否足够限制,这种方法可能就足够了。

撰写回答