[英]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
問題:
TL; DR:由於名稱綁定在Python中的工作方式,通常無法獲取傳遞給函數的變量的名稱。 某些Python對象確實具有name屬性,但這與綁定到賦值語句中的對象的名稱不同。
當您打印id
時,您的代碼會給您帶來誤導性信息。 你實際上並沒有打印對象的id
,你在locals()
dict
打印名稱字符串的id
。
此外,當你在函數中獲得locals()
,它會顯示函數本地的東西。 因此,要獲取有關函數外部的本地對象的信息,您需要為函數訪問您感興趣的實際locals()
字典。
下面是代碼的修改版本,它修復了id
內容,並將locals()
數據的副本傳遞給addr_type
函數。
請注意,當您為a
或c
調用該函數時,它會打印兩個名稱的信息。
我還增加了,告訴你如何使用它的打印功能的名稱,幾行__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()
,則只能獲取此范圍中定義的變量。 這就是它打印的原因
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.