簡體   English   中英

函數來打印傳遞變量的名稱

[英]function to print name of passed variable

我最初的目標是創建一個函數,它將打印給定對象的類型和內存地址。 為了盡可能地普及,我還想包含變量名,如下所示:

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

為此,我需要知道傳遞給該函數的變量的名稱。 這個頁面建議下面的代碼(它有點修改版本,但想法保持不變,迭代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中的工作方式,通常無法獲取傳遞給函數的變量的名稱。 某些Python對象確實具有name屬性,但這與綁定到賦值語句中的對象的名稱不同。

當您打印id時,您的代碼會給您帶來誤導性信息。 你實際上並沒有打印對象的id ,你在locals() dict打印名稱字符串的id

此外,當你在函數中獲得locals() ,它會顯示函數本地的東西。 因此,要獲取有關函數外部的本地對象的信息,您需要為函數訪問您感興趣的實際locals()字典。

下面是代碼的修改版本,它修復了id內容,並將locals()數據的副本傳遞給addr_type函數。

請注意,當您為ac調用該函數時,它會打印兩個名稱的信息。

我還增加了,告訴你如何使用它的打印功能的名稱,幾行__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__

產量

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

您可能會發現,閱讀由Stack Overflow資深人士Ned Batchelder撰寫的關於Python名稱和值的優秀文章Facts和myths會很有幫助。


更新

這是一個簡單的函數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)

產量

a 1
b 2
c 3
t 42

我從問題的第二部分開始。 這里的問題是,您正在打印hex(id(k)) 你應該打印hex(id(v))

locals()搜索名稱不是一個好主意locals()

更新並返回表示當前本地符號表的字典。

如果在函數內部調用locals() ,則只能獲取此范圍中定義的變量。 這就是它打印的原因

k: obj
v: 11
a: 0x7fc9253198a0

您必須將locals()字典傳遞給type_addr()以獲取變量來自范圍的一些信息。

a = 7
type_addr(a, locals())

另一方面,如果您有多個具有相同值的變量,您很可能會得到錯誤的名稱(如果您不打印所有這些名稱)。

所以遵循Python的禪宗

顯式優於隱式。

我建議將名稱傳遞給明確打印。

def type_addr(obj, msg):
    print '%s: %s %s' % (msg, type(obj).__name__, hex(id(obj)))

a = 11
type_addr(a, 'a')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM