警告: 这个问题在措辞上看似简单,但可能需要额外的智力来回答它。尝试采用How can I get the name of an object in Python?中的方法并不是一个有效的答案(您可能需要先阅读它)。根据定义,通过对象的这种方法是不明确的,因为任何对象都可以被几个名称引用,甚至没有。建议的方法需要回到解析步骤,其中对象尚未存在。
背景:我正在探索如何在Python中创建允许我们取消一些冗余的构造,例如:在进行单元测试时:
y = 5
print("%s: %s" % ('y', y))
最好写一下:
y = 5
print(info(y)) => "Value of 'y' is 5"
注意:这可以通过传递一个字符串然后将其转换为id来反过来解决,例如, print(info('y')
使用globals()['y']
之类的内容。但是在这里我们想要从
问题:如果在源代码中给出一个名为x的标识符,是否可以编写一个symbol
函数来返回与x对应的字符串?< / p>
语义上,如果我写
x = [1, 2, 3, 4] # whatever object
从源代码中可以明显看出x是字符串'x'。
换句话说,是否有可能(在标准Python中)编写一个符号函数(仅用于输入名称),给定x,将其视为符号的确切位置调用函数,并返回字符串'x'?
x = [1, 2, 3, 4] # whatever object
y = x
symbol(x) = 'x'
symbol(y) = 'y'
答案是明确的:调用函数时,x和y在源代码中用作符号,因此符号的结果必须是字符串等效于符号(分别为'x'和'y')。
我意识到这可能是一个很好的二度内省工作(在源代码(AST?)中找到函数被调用的地方然后用它来推理)。然而,它可以用今天存在的Python来完成吗?
因此,如果提议的符号函数有效,则应该能够编写(通常用于单元测试):
x = 5
y = x
print("The value of %s is %s", symbol(x), x) => 5
print("The value of %s is %s", symbol(y), y) => 5
然后info
函数可以写成:
def info(y):
return("%s: %s" % (symbol(y), y))
注1:为了一般性,解决方案应该在标准Python中工作,但其他实现的答案也是可以接受的。
注2:如果您认为“符号”不是此功能或概念的正确名称,欢迎您指出。
注3:这是一个确切的问题:假设在代码中使用符号Y,则写一个符号函数,它给出符号(Y)='Y',而不管其中的对象是什么符号指向(类,对象等)。
答案 0 :(得分:2)
这可以通过阅读调用symbol
函数的源代码来完成:
import inspect
import re
def symbol(arg):
frame = inspect.currentframe().f_back
frameinfo = inspect.getouterframes(frame)[0]
calling_code = frameinfo[4][frameinfo[5]].strip()
del frame
# this adds support for multiple calls in the same line
matches = re.findall(r'\bsymbol\((\w+)\)', calling_code)
match = matches[symbol.call_count]
symbol.call_count += 1
if symbol.call_count == len(matches):
symbol.call_count = 0
return match
symbol.call_count = 0
x = 3
print(symbol(x)) # output: x
注意事项:
可以通过字符串绊倒:
fake = "symbol(fake)"; print(symbol(5))
# output: fake
答案 1 :(得分:0)
我不确定问题是否正确,但这是一个在[Python]: globals()中搜索符号的示例:
import sys
x = [1, 2, 33]
def dummy():
pass
def symbol(obj):
globals_dict = globals()
for name in globals_dict:
if obj is globals_dict[name]:
return name
def main():
for obj in [sys, x, dummy, symbol, main]:
obj_name = symbol(obj)
print(obj_name, type(obj_name))
if __name__ == "__main__":
main()
<强>输出强>:
E:\Work\Dev\StackOverflow\q47091183>"E:\WinOBT\1.0.0.0\OPSWpython\2.7.10__00\x86\python.exe" a.py ('sys', <type 'str'>) ('x', <type 'str'>) ('dummy', <type 'str'>) ('symbol', <type 'str'>) ('main', <type 'str'>)