How to get name of function's actual parameters in Python?

余生颓废 提交于 2019-12-02 09:08:07

问题


For example:

def func(a):
    # how to get the name "x"

x = 1
func(x)

If I use inspect module I can get the stack frame object:

import inspect
def func(a):
    print inspect.stack()

out:

[
(<frame object at 0x7fb973c7a988>, 'ts.py', 9, 'func', ['  stack = inspect.stack()\n'], 0)

(<frame object at 0x7fb973d74c20>, 'ts.py', 18, '<module>', ['func(x)\n'], 0)
]

or use inspect.currentframe() I can get the current frame.

But I can only get the name "a" by inspect the function object.

Use inspect.stack I can get the call stack:"['func(x)\n']",

How can I get the name of actual parameters("x" here) when call the func by parsing the "['func(x)\n']"?

If I call func(x) then I get "x"

if I call func(y) then I get "y"

Edit:

A example:

def func(a):

    # Add 1 to acttual parameter
    ...

x = 1
func(x)
print x # x expected to 2

y = 2
func(y)
print y # y expected to 3

回答1:


Looking at your comment explanations, the reason you are trying to do this is:

Because I want to impelment Reference Parameters like in C++

You can't do that. In python, everything is passed by value, but that value is a reference to the object you pass. Now, if that object is mutable (like a list), you can modify it, but if it's immutable, a new object is created and set. In your code example, x is an int which is immutable, so if you want to change the value of x it, just return its new value from the function you are invoking:

def func(a):
    b = 5 * a
    # ... some math
    return b


x = 1
x = func(x)

So what if you want to return multiple values? Use a tuple!

def func(a, b):
    a, b = 5 * b, 6 * a
    # ...
    return b, a

a, b = 2, 3
a, b = func(a, b)



回答2:


That is feasible, up to a point - but nonetheless,useless in any kind of "real code". You can use it for backyard magic tricks:

Just retrieve the calling stack_frame like you are doing, then loop linearly through the variables available in the calling frame for one that references the same object you got as a parameter. The variables are in the f_locals and f_globals dictionaries which are attributes of the frame object.

Of course, the parameter passed may not be in a variable name to start with: it might be a constant in the caller, or it might be inside a dict or a list.

Either way, as @Nasser put it in the answer: it is not the way Python works. Objects exist in memory, and variable names, in each scope, just point to those objects. The names themselves are meaningless otherwise.

import inspect
from itertools import chain

def magic(x):
    # note that in Python2, 'currentframe' could get a parameter
    # to indicate which frame you want on the stack. Not so in Python3
    fr = inspect.currentframe().f_back
    for var_name, value in chain(fr.f_locals.items(),  fr.f_globals.items()):
        if value is x:
            print ("The variable name in the caller context is {}".format(var_name))


def caler():
   y = "My constant"
   magic(y)



回答3:


use lists as references

def func(a):
   a[0] = a[0] + 1

x = [1]
func(x)
print x[0] # x expected to 2

y = [2]
func(y)
print y[0] # y expected to 3



回答4:


This is my final solution. Use ast to parse the function statement and get the args.:

import inspect
import re
import ast

def func(a,b,c):
  stack = inspect.stack()
  stack_pre = stack[1]
  function_call_string = ';'.join( stack_pre[4] ).strip('\n')
  ret = re.search(r'(%s[ ]*\(.*\))' % func.func_name, function_call_string)
  striped_function_call_string = ret.group()
  parser = ast.parse(striped_function_call_string)

  frame = inspect.currentframe()
  for arg in parser.body[0].value.args:
    iter_frame = frame.f_back
    while iter_frame:
      if arg.id in iter_frame.f_locals:
        iter_frame.f_locals[arg.id] += 1
        break
      iter_frame = iter_frame.f_back

x=1;y=2;z=3;func(x,y,z)
print x,y,z

Out: 2 3 4



来源:https://stackoverflow.com/questions/27545684/how-to-get-name-of-functions-actual-parameters-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!