反正有没有在python中获取函数的传递参数的名称?

时间:2012-12-11 19:58:37

标签: python

我想知道传递给函数时局部变量名是什么。我不确定这是否可行。让我们考虑这个例子:

功能定义:

def show(x):
  print(x)

用法:

a = 10
show(a)

这打印10.但我喜欢打印“a = 10”。这在python中是否可行?

7 个答案:

答案 0 :(得分:5)

不完全是这样的。但是,您可以实现类似的目标:

def show(**kwargs):
  print(', '.join('%s=%s' % kv for kv in kwargs.items()))

show(a=20)

答案 1 :(得分:4)

不,您无法知道用于将值传递给函数的局部变量的名称。

无论如何,这是一项不可能完成的任务。以下示例中的变量名称是什么?

arguments = ('a', 1, 10)
somefunction(*(arguments[:2] + [10]))

这里我们传入3个参数,其中两个来自我们之前定义的元组,一个文字值,所有三个都使用变量参数列表语法传入。

答案 2 :(得分:3)

我喜欢Python编程常见问题解答中的answer to this question,引用Fredrik Lundh:

  

就像你在门廊上找到那只猫的名字一样:   猫(对象)本身不能告诉你它的名字,它   真的不在乎 - 所以找出它所谓的唯一方法就是   询问所有邻居(名称空间)是否是他们的猫(对象)...

     

....如果您发现它被许多名字所知,或者根本没有名字,请不要感到惊讶!

答案 3 :(得分:2)

我预示以下解决方案会受到一些批评

def show(*x):
    for el in x:
        fl = None
        for gname,gobj in globals().iteritems():
            if el==gobj:
                print '%s == %r' % (gname,el)
                fl = True
        if not fl:
            print 'There is no identifier assigned to %r in the global namespace' % el

un = 1
y = 'a'
a = 12
b = c = 45
arguments = ('a', 1, 10)
lolo = [45,'a',a,'heat']

print '============================================'
show(12)
show(a)
print '============================================'
show(45)
print
show(b)
print '============================================'
show(arguments)
print
show(('a', 1, 10))
print '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
show(*arguments)
print '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'
show(*(arguments[1:3] + (b,)))

结果

============================================
a == 12
a == 12
============================================
c == 45
b == 45

c == 45
b == 45
============================================
arguments == ('a', 1, 10)

arguments == ('a', 1, 10)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
y == 'a'
un == 1
There is no identifier assigned to 10 in the global namespace
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
un == 1
There is no identifier assigned to 10 in the global namespace
c == 45
b == 45

答案 4 :(得分:1)

似乎在Python中它是不可能的,但它实际上可以在C ++中使用。

#define show(x)   std::cout << #x << " = " << x << std::endl

答案 5 :(得分:1)

使用readline

的新解决方案

如果您正在进行互动会话,这是一个非常天真的解决方案,通常可以正常运行:

def show(x):
    from readline import get_current_history_length, get_history_item
    print(get_history_item(get_current_history_length()).strip()[5:-1] + ' = ' + str(x))

所有这一切都是在交互式会话缓冲区中读取最后一行输入,删除任何前导或尾随空格,然后提供除前五个字符(希望show()和最后一个字符(希望{{ 1}}),因此留下任何传入的内容。

示例:

)

如果您使用随附的Python版本在OS X上,则默认情况下没有安装>>> a = 10 >>> show(a) a = 10 >>> b = 10 >>> show(b) b = 10 >>> show(10) 10 = 10 >>> show([10]*10) [10]*10 = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10] >>> show('Hello' + 'World'.rjust(10)) 'Hello' + 'World'.rjust(10) = Hello World ,但您可以通过readline安装它。如果您使用的是Windows,则pip不存在...您可能可以使用readline中的pyreadline,但我从未尝试过,所以我不能说它是否是可接受的替代品。

我让上面的代码更加防弹,作为读者的练习。需要考虑的是如何处理这样的事情:

pip

如果您希望这种事情从脚本中显示变量名称,您可以查看使用inspect并获取调用帧的源代码。但是考虑到我无法想到为什么你会想要在脚本中使用show(show(show(10))) show( 10 ) 或者为什么你会使函数复杂化只是为了处理人们如上所述故意搞砸它,我不会浪费我现在的时间搞清楚了。

使用show()

的原始解决方案

这是我原来的解决方案,它更复杂,并且有更明显的警告,但更便携,因为它只使用inspect,而不是inspect,所以在所有平台上运行,无论你是否在交互式会话或脚本中:

readline

这是一个完美运作的案例(问题中的那个):

def show(x):

    from inspect import currentframe

    # Using inspect, figure out what the calling environment looked like by merging
    #   what was available from builtin, globals, and locals.
    # Do it in this order to emulate shadowing variables
    #   (locals shadow globals shadow builtins).

    callingFrame = currentframe().f_back
    callingEnv = callingFrame.f_builtins.copy()
    callingEnv.update(callingFrame.f_globals)
    callingEnv.update(callingFrame.f_locals)

    # Get the variables in the calling environment equal to what was passed in.
    possibleRoots = [item[0] for item in callingEnv.items() if item[1] == x]

    # If there are none, whatever you were given was more than just an identifier.
    if not possibleRoots:
        root = '<unnamed>'
    else:
        # If there is exactly one identifier equal to it,
        #   that's probably the one you want.
        # This assumption could be wrong - you may have been given
        #   something more than just an identifier.
        if len(possibleRoots) == 1:
            root = str(possibleRoots[0])
        else:
            # More than one possibility? List them all.
            # Again, though, it could actually be unnamed.
            root = '<'
            for possibleRoot in possibleRoots[:-1]:
                root += str(possibleRoot) + ', '
            root += 'or ' + str(possibleRoots[-1]) + '>'

    print(root + ' = ' + str(x))

这是另一个有趣的案例:

>>> a = 10
>>> show(a)
a = 10

现在你知道如何在Python解释器中实现该功能 - >>> show(quit) quit = Use quit() or Ctrl-Z plus Return to exit quit的内置标识符,说明如何正确退出。

这里有一些情况,它比你想要的要少,但是......可以接受吗?

str

这是一个打印出真实陈述的情况,但绝对不是你想要的:

>>> b = 10
>>> show(b)
<a, or b> = 10
>>> show(11)
<unnamed> = 11
>>> show([a])
<unnamed> = [10]

答案 6 :(得分:0)

这是一个只有在 Python 3.6 中使用 f-strings 才成为可能的答案:

x = 10
print(f'{x=}')  # Outputs x=10