如何获取传递给函数的变量的原始变量名

时间:2023-01-30 00:38:13

Is it possible to get the original variable name of a variable passed to a function? E.g.

是否可以获取传递给函数的变量的原始变量名?例如。

foobar = "foo"

def func(var):
    print var.origname

So that:

以便:

func(foobar)

Returns:

返回:

>>foobar

>> foobar的

EDIT:

编辑:

All I was trying to do was make a function like:

我所要做的就是做一个像以下的功能:

def log(soup):
    f = open(varname+'.html', 'w')
    print >>f, soup.prettify()
    f.close()

.. and have the function generate the filename from the name of the variable passed to it.

..并让函数从传递给它的变量的名称生成文件名。

I suppose if it's not possible I'll just have to pass the variable and the variable's name as a string each time.

我想如果不可能我只需要每次都将变量和变量的名称作为字符串传递。

7 个解决方案

#1


12  

You can't. It's evaluated before being passed to the function. All you can do is pass it as a string.

你不能。它在传递给函数之前进行了评估。您所能做的就是将其作为字符串传递。

#2


45  

EDIT: To make it clear, I don't recommend using this AT ALL, it will break, it's a mess, it won't help you in anyway, but it's doable for entertainment/education purposes.

编辑:为了说清楚,我不建议使用这个全部,它会破坏,它是一个烂摊子,它无论如何都无济于事,但它可用于娱乐/教育目的。

You can hack around with the inspect module, I don't recommend that, but you can do it...

您可以使用检查模块进行操作,我不建议这样做,但您可以这样做......

import inspect

def foo(a, f, b):
    frame = inspect.currentframe()
    frame = inspect.getouterframes(frame)[1]
    string = inspect.getframeinfo(frame[0]).code_context[0].strip()
    args = string[string.find('(') + 1:-1].split(',')

    names = []
    for i in args:
        if i.find('=') != -1:
            names.append(i.split('=')[1].strip())

        else:
            names.append(i)

    print names

def main():
    e = 1
    c = 2
    foo(e, 1000, b = c)

main()

Output:

输出:

['e', '1000', 'c']

#3


11  

Looks like Ivo beat me to inspect, but here's another implementation:

看起来Ivo打我去检查,但这是另一个实现:

import inspect

def varName(var):
    lcls = inspect.stack()[2][0].f_locals
    for name in lcls:
        if id(var) == id(lcls[name]):
            return name
    return None

def foo(x=None):
    lcl='not me'
    return varName(x)

def bar():
    lcl = 'hi'
    return foo(lcl)

bar()
# 'lcl'

Of course, it can be fooled:

当然,它可以被愚弄:

def baz():
    lcl = 'hi'
    x='hi'
    return foo(lcl)

baz()
# 'x'

Moral: don't do it.

道德:不要这样做。

#4


8  

To add to Michael Mrozek's answer, you can extract the exact parameters versus the full code by:

要添加到Michael Mrozek的答案中,您可以通过以下方式提取确切参数与完整代码:

import re
import traceback

def func(var):
    stack = traceback.extract_stack()
    filename, lineno, function_name, code = stack[-2]
    vars_name = re.compile(r'\((.*?)\).*$').search(code).groups()[0]
    print vars_name
    return

foobar = "foo"

func(foobar)

# PRINTS: foobar

#5


3  

If you want a Key Value Pair relationship, maybe using a Dictionary would be better?

如果你想要一个Key Value Pair关系,也许使用Dictionary会更好?

...or if you're trying to create some auto-documentation from your code, perhaps something like Doxygen (http://www.stack.nl/~dimitri/doxygen/) could do the job for you?

...或者如果您正在尝试从代码中创建一些自动文档,也许Doxygen(http://www.stack.nl/~dimitri/doxygen/)之类的东西可以为您完成这项工作?

#6


3  

Another way you can try if you know what the calling code will look like is to use traceback:

如果你知道调用代码的样子,你可以尝试的另一种方法是使用traceback:

def func(var):
    stack = traceback.extract_stack()
    filename, lineno, function_name, code = stack[-2]

code will contain the line of code that was used to call func (in your example, it would be the string func(foobar)). You can parse that to pull out the argument

代码将包含用于调用func的代码行(在您的示例中,它将是字符串func(foobar))。您可以解析它以取出参数

#7


1  

@Ivo Wetzel's answer works in the case of function call are made in one line, like

@Ivo Wetzel的答案工作在函数调用的情况下都是在一行中制作的

e = 1 + 7
c = 3
foo(e, 100, b=c)

In case that function call is not in one line, like:

如果函数调用不在一行中,例如:

e = 1 + 7
c = 3
foo(e,
    1000,
    b = c)

below code works:

以下代码有效:

import inspect, ast

def foo(a, f, b):
    frame = inspect.currentframe()
    frame = inspect.getouterframes(frame)[1]
    string = inspect.findsource(frame[0])[0]

    nodes = ast.parse(''.join(string))

    i_expr = -1
    for (i, node) in enumerate(nodes.body):
        if hasattr(node, 'value') and isinstance(node.value, ast.Call)
            and hasattr(node.value.func, 'id') and node.value.func.id == 'foo'  # Here goes name of the function:
            i_expr = i
            break

    i_expr_next = min(i_expr + 1, len(nodes.body)-1)  
    lineno_start = nodes.body[i_expr].lineno
    lineno_end = nodes.body[i_expr_next].lineno if i_expr_next != i_expr else len(string)

    str_func_call = ''.join([i.strip() for i in string[lineno_start - 1: lineno_end]])
    params = str_func_call[str_func_call.find('(') + 1:-1].split(',')

    print(params)

You will get:

你会得到:

[u'e', u'1000', u'b = c']

But still, this might break.

但是,这可能会破裂。

#1


12  

You can't. It's evaluated before being passed to the function. All you can do is pass it as a string.

你不能。它在传递给函数之前进行了评估。您所能做的就是将其作为字符串传递。

#2


45  

EDIT: To make it clear, I don't recommend using this AT ALL, it will break, it's a mess, it won't help you in anyway, but it's doable for entertainment/education purposes.

编辑:为了说清楚,我不建议使用这个全部,它会破坏,它是一个烂摊子,它无论如何都无济于事,但它可用于娱乐/教育目的。

You can hack around with the inspect module, I don't recommend that, but you can do it...

您可以使用检查模块进行操作,我不建议这样做,但您可以这样做......

import inspect

def foo(a, f, b):
    frame = inspect.currentframe()
    frame = inspect.getouterframes(frame)[1]
    string = inspect.getframeinfo(frame[0]).code_context[0].strip()
    args = string[string.find('(') + 1:-1].split(',')

    names = []
    for i in args:
        if i.find('=') != -1:
            names.append(i.split('=')[1].strip())

        else:
            names.append(i)

    print names

def main():
    e = 1
    c = 2
    foo(e, 1000, b = c)

main()

Output:

输出:

['e', '1000', 'c']

#3


11  

Looks like Ivo beat me to inspect, but here's another implementation:

看起来Ivo打我去检查,但这是另一个实现:

import inspect

def varName(var):
    lcls = inspect.stack()[2][0].f_locals
    for name in lcls:
        if id(var) == id(lcls[name]):
            return name
    return None

def foo(x=None):
    lcl='not me'
    return varName(x)

def bar():
    lcl = 'hi'
    return foo(lcl)

bar()
# 'lcl'

Of course, it can be fooled:

当然,它可以被愚弄:

def baz():
    lcl = 'hi'
    x='hi'
    return foo(lcl)

baz()
# 'x'

Moral: don't do it.

道德:不要这样做。

#4


8  

To add to Michael Mrozek's answer, you can extract the exact parameters versus the full code by:

要添加到Michael Mrozek的答案中,您可以通过以下方式提取确切参数与完整代码:

import re
import traceback

def func(var):
    stack = traceback.extract_stack()
    filename, lineno, function_name, code = stack[-2]
    vars_name = re.compile(r'\((.*?)\).*$').search(code).groups()[0]
    print vars_name
    return

foobar = "foo"

func(foobar)

# PRINTS: foobar

#5


3  

If you want a Key Value Pair relationship, maybe using a Dictionary would be better?

如果你想要一个Key Value Pair关系,也许使用Dictionary会更好?

...or if you're trying to create some auto-documentation from your code, perhaps something like Doxygen (http://www.stack.nl/~dimitri/doxygen/) could do the job for you?

...或者如果您正在尝试从代码中创建一些自动文档,也许Doxygen(http://www.stack.nl/~dimitri/doxygen/)之类的东西可以为您完成这项工作?

#6


3  

Another way you can try if you know what the calling code will look like is to use traceback:

如果你知道调用代码的样子,你可以尝试的另一种方法是使用traceback:

def func(var):
    stack = traceback.extract_stack()
    filename, lineno, function_name, code = stack[-2]

code will contain the line of code that was used to call func (in your example, it would be the string func(foobar)). You can parse that to pull out the argument

代码将包含用于调用func的代码行(在您的示例中,它将是字符串func(foobar))。您可以解析它以取出参数

#7


1  

@Ivo Wetzel's answer works in the case of function call are made in one line, like

@Ivo Wetzel的答案工作在函数调用的情况下都是在一行中制作的

e = 1 + 7
c = 3
foo(e, 100, b=c)

In case that function call is not in one line, like:

如果函数调用不在一行中,例如:

e = 1 + 7
c = 3
foo(e,
    1000,
    b = c)

below code works:

以下代码有效:

import inspect, ast

def foo(a, f, b):
    frame = inspect.currentframe()
    frame = inspect.getouterframes(frame)[1]
    string = inspect.findsource(frame[0])[0]

    nodes = ast.parse(''.join(string))

    i_expr = -1
    for (i, node) in enumerate(nodes.body):
        if hasattr(node, 'value') and isinstance(node.value, ast.Call)
            and hasattr(node.value.func, 'id') and node.value.func.id == 'foo'  # Here goes name of the function:
            i_expr = i
            break

    i_expr_next = min(i_expr + 1, len(nodes.body)-1)  
    lineno_start = nodes.body[i_expr].lineno
    lineno_end = nodes.body[i_expr_next].lineno if i_expr_next != i_expr else len(string)

    str_func_call = ''.join([i.strip() for i in string[lineno_start - 1: lineno_end]])
    params = str_func_call[str_func_call.find('(') + 1:-1].split(',')

    print(params)

You will get:

你会得到:

[u'e', u'1000', u'b = c']

But still, this might break.

但是,这可能会破裂。