Finding an identifier's string equivalent (as expressed in source code)?
注意:这个问题的措辞看似简单,但可能需要额外的智力努力来回答。尝试采用一种方法,比如如何在Python中获取对象的名称?不是有效答案(您可能需要先阅读)。根据定义,通过对象的这种方法是不明确的,因为任何对象都可以被多个名称引用,甚至没有名称引用。建议的方法要求回到解析的步骤,对象还没有任何存在。
背景:我正在探索如何在Python中创建允许我们消除一些冗余的结构,例如,在进行单元测试时:
1 2 | y = 5 print("%s: %s" % ('y', y)) |
最好是写:
1 2 | y = 5 print(info(y)) =>"Value of 'y' is 5" |
号
注意:这可以通过另一种方式解决,方法是传递一个字符串,然后将其转换为一个ID,例如,使用
问题:在源代码中给定一个名为x的标识符,是否可以编写一个返回x对应字符串的
在语义上,如果我写
1 | x = [1, 2, 3, 4] # whatever object |
从源代码中可以明显看出,x是字符串"x"。
换言之,是否可以(在标准python中)编写一个符号函数(只需输入一个名称),给定x,在函数被调用的确切位置将其视为符号,并返回字符串"x"?
1 2 3 4 | x = [1, 2, 3, 4] # whatever object y = x symbol(x) = 'x' symbol(y) = 'y' |
。
答案是明确的:在调用函数时,x和y被用作源代码中的符号,因此符号的结果必须是与符号等效的字符串("x"和"y")。
我意识到这可能是一个很好的二级反省工作(在源代码(ast?)中找到位置)。调用函数的位置,然后进行推理)。但是,是否可以像现在这样使用Python?
因此,如果建议的符号函数有效,那么应该能够编写(通常用于单元测试):
1 2 3 4 | 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 |
那么,
1 2 | def info(y): return("%s: %s" % (symbol(y), y)) |
。
注1:出于通用性的考虑,解决方案应该在标准的Python中工作,但是对于其他实现的答案也是可以接受的。
注2:如果您觉得"符号"不是这个函数或概念的正确名称,欢迎您指出这一点。
注3:这是一个精确的问题:考虑到代码中使用了符号Y,编写一个符号函数,它给出符号(Y)='Y',而不考虑符号指向的对象(类、对象等)。
这可以通过读取调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
号
1 2 | x = 3 print(symbol(x)) # output: x |
注意事项:
- 不能在交互式会话或任何其他无法读取源代码的情况下工作
可能被串绊倒:
1
2fake ="symbol(fake)"; print(symbol(5))
# output: fake。
不确定我的问题是否正确,但下面是一个在:globals()中搜索符号的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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() |
输出:
1
2
3
4
5
6 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'>)
号