How to get/set local variables of a function (from outside) in Python?

Question:

If I have a function (in Python 2.5.2) like:

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

My questions are:

  1. How to get the local variables (a,b) of the function from outside without using locals() inside the function? (kind of reflection)
  2. Is it possible to set a local variable (say x) from outside so that the commented line works? (I know it sounds weird).

Thanks in advance.

EDIT:

Everyone is asking for a use-case. But it is a weird situation. (Don’t blame me, I did not create it). Here is the scenario:

  1. I have an encrypted python source file containing a python function.
  2. A C extension module decrypts it and builds that function in-memory.
  3. A main python program first calls the C extension with that encrypted file location.
  4. Then the main program calls the function that has been built in-memory (by the C extension)
  5. But main program needs to know the local variables of that function (Dont ask me why, it was not me)
  6. For some (damn) reason, main program needs to set a variable too (weirdest of all)
Asked By: mshsayem

||

Answers:

I’m not sure what your use-case is, but this may work better as a class. You can define the __call__ method to make a class behave like a function.

e.g.:

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

(this is based on your toy example, so the code doesn’t make much sense. If you give more details, we may be able to provide better advice)

Answered By: John Fouhy

The function’s locals change whenever the function is run, so there’s little meaning to access them while the function isn’t running.

Answered By: orip

No. A function that isn’t being run doesn’t have locals; it’s just a function. Asking how to modify a function’s locals when it’s not running is like asking how to modify a program’s heap when it’s not running.

You can modify constants, though, if you really want to.

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

It’s a hack, because there’s no way to know which constant in co.co_consts is which; this uses a sentinel value to figure it out. Depending on whether you can constrain your use cases enough, that might be enough.

Answered By: Glenn Maynard

Not sure if this is what you mean, but as functions are objects in Python you can bind variables to a function object and access them from ‘outside’:

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

Please excuse me if I am terribly wrong… I´m a Python and programming beginner myself…

Answered By: Titusz

Expecting a variable in a function to be set by an outside function BEFORE that function is called is such bad design that the only real answer I can recommend is changing the design. A function that expects its internal variables to be set before it is run is useless.

So the real question you have to ask is why does that function expect x to be defined outside the function? Does the original program that function use to belong to set a global variable that function would have had access to? If so, then it might be as easy as suggesting to the original authors of that function that they instead allow x to be passed in as an argument. A simple change in your sample function would make the code work in both situations:

def sample_func(x_local=None):
  if not x_local:
    x_local = x
  a = 78
  b = range(5)
  c = a + b[2] - x_local

This will allow the function to accept a parameter from your main function the way you want to use it, but it will not break the other program as it will still use the globally defined x if the function is not given any arguments.

Answered By: hevans66
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.