打印传递变量名称的函数

2023-11-30

我最初的目标是创建一个函数来打印给定对象的类型和内存地址。为了尽可能通用,我还想包含变量名称,如下所示:

>>> a=10
>>> print type_addr(a)
a: int, 0x13b8080

为此,我需要知道传递给该函数的变量的名称。这page建议使用以下代码(它有一点修改版本,但想法保持不变,迭代locals().iteritems()。我知道它不安全,并且在给定链接上提到了几个陷阱,但我的计划是改进它):

#!/usr/bin/python

a = b = c = 10
b = 11

for k, v in list(locals().iteritems()):
  if v is b:
  # if id(v) == id(b):
    print "k: %s" % k
    print "v: %s" % v
    print "a: %s" % hex(id(k))

上述代码的输出是:

k: b
v: 11
a: 0x7fece0f305f8

我的下一个目标是制作一个子例程,它会给我想要的结果,所以我尝试将其包装到子例程中:

#!/usr/bin/python

a = b = c = 10
b = 11

def addr_type(obj):
  for k, v in list(locals().iteritems()):
    # if id(v) == id(a):
    if v is obj:
      print "k: %s" % k
      print "v: %s" % v
      print "a: %s" % hex(id(k))

for k, v in list(locals().iteritems()):
  if v is b:
  # if id(v) == id(b):
    print "k: %s" % k
    print "v: %s" % v
    print "a: %s" % hex(id(k))

print "#################"

addr_type(b)

上述代码的输出是:

k: b
v: 11
a: 0x7fc9253715f8
#################
k: obj
v: 11
a: 0x7fc9253198a0

正如你所看到的,变量的名称和地址都不相同。然后我开始深入挖掘并尝试以下操作:

#!/usr/bin/python
a = b = c = 10
b = 11

for k, v in list(locals().iteritems()):
   print "k: %s" % k
   print "v: %s" % v
   print "a: %s" % hex(id(k))
   print "##############"


if a is b:
    print "a and b is the same objects"
else:
    print "a and b is NOT the same objects"


if a is c:
    print "a and c is the same objects"
else:
    print "a and c is NOT the same objects"


if b is c:
    print "b and c is the same objects"
else:
    print "b and c is NOT the same objects"

返回:

k: a
v: 10
a: 0x7ff07d54b5d0
##############
k: c
v: 10
a: 0x7ff07d54bbe8
##############
k: b
v: 11
a: 0x7ff07d54b5f8
##############
<Some loaded modules here but nothing interesting>
##############
a and b is NOT the same objects
a and c is the same objects
b and c is NOT the same objects

问题:

  1. 如何重写工作代码并制作打印传递变量名称的函数?
  2. 为什么相同的对象有不同的地址?

TL; DR:由于名称绑定在 Python 中的工作方式,您通常can't获取传递给函数的变量的名称。一些Python对象do有一个 name 属性,但这与您在赋值语句中绑定到对象的名称不同。

您的代码在打印时给您提供了误导性信息ids。你实际上并没有打印ids 的对象,您正在打印id中名称字符串的 slocals() dict.

另外,当你得到locals()在函数内部,它向您显示函数本地的内容。因此,要获取有关函数外部的本地对象的信息,您需要让函数访问实际的对象locals()听写你感兴趣的内容。

下面是代码的修改版本,修复了id的东西,还传递了一份副本locals()数据到addr_type功能。

请注意,当您调用该函数时a or c它打印两个名字的信息。

我还添加了几行内容来展示您如何can使用其打印函数的名称__name__属性。请注意,当我们打印时new_name.__name__它只是打印addr_type,因为这是函数的值__name__属性,事实上我们也将它绑定到new_name是无关紧要的。

#!/usr/bin/env python

def addr_type(context, obj):
    for k, v in context:
        # if id(v) == id(a):
        if v is obj:
            print "k: %s" % k
            print "v: %s" % v
            print "a: %s" % hex(id(v))
            print
    print 15 * "-"


a = b = c = 10
b = 11

for k, v in list(locals().iteritems()):
    if k.startswith('__'):
        continue
    print "k: %s" % k
    print "v: %s" % v
    print "a: %s" % hex(id(v))
    print "##############"

print

if a is b:
    print "a and b is the same objects"
else:
    print "a and b is NOT the same objects"


if a is c:
    print "a and c is the same objects"
else:
    print "a and c is NOT the same objects"


if b is c:
    print "b and c is the same objects"
else:
    print "b and c is NOT the same objects"

print

context = list(locals().iteritems())
addr_type(context, a)
addr_type(context, b)
addr_type(context, c)

new_name = addr_type
print 'Function names =', addr_type.__name__, new_name.__name__

output

k: a
v: 10
a: 0x8dafd24
##############
k: c
v: 10
a: 0x8dafd24
##############
k: b
v: 11
a: 0x8dafd18
##############
k: addr_type
v: <function addr_type at 0xb748e17c>
a: 0xb748e17cL
##############

a and b is NOT the same objects
a and c is the same objects
b and c is NOT the same objects

k: a
v: 10
a: 0x8dafd24

k: c
v: 10
a: 0x8dafd24

---------------
k: b
v: 11
a: 0x8dafd18

---------------
k: a
v: 10
a: 0x8dafd24

k: c
v: 10
a: 0x8dafd24

---------------
Function names = addr_type addr_type

您可能会发现研究这篇优秀文章很有帮助关于 Python 名称和值的事实和神话,由 Stack Overflow 资深人士 Ned Batchelder 撰写。


Update

这是一个简单的函数,show,它会打印您传递给它的名称,以及您传递给它的字典中该名称的值。通过传递它locals()字典这允许它在本地范围内按名称查找对象。在函数内部,这是函数的局部变量。在函数之外,这就是所有全局变量。

def show(*args, names):
    for s in args:
        print(s, names.get(s, 'Not found!'))

def test(t):
    a = 1
    b = 2
    c = 3
    show('a', 'b', 'c', 't', names=locals())

test(42)

output

a 1
b 2
c 3
t 42
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

打印传递变量名称的函数 的相关文章

随机推荐