Python - 在全局作用域中获取对象的所有变量名

6
我将用一个例子来解释:
list_1 = [1, 2, 3]
list_2 = list_3 = list_1 # reference copy

print(magic_method(list_1))
# Should print ['list_1', 'list_2', 'list_3']

set_1 = {'a', 'b'}
print(magic_method(set_1))
# Should print ['set_1']

需求:返回指向相同引用的所有变量名称。这在Python中是否可能?

我在考虑遍历globals()locals(),然后将id进行比较。有更好的方法吗?


@donkopotamus 我认为它不需要太复杂。我现在考虑的只是全局范围。 - cs95
尽管您没有明确编写它,但我理解您所拥有的是 def magic_method(obj): return [name for name, val in globals().items() if val is obj],您希望有更直接的东西? - jdehesa
1
其他容器、类等下的引用怎么办?list_4 = [list_1, 0]; class A: foo = list_1. - Ashwini Chaudhary
@AshwiniChaudhary,我也很想知道针对你提到的容器情况如何制定当前解决方案的扩展。你有任何想法吗? - cs95
1
基于gc.get_referrers的递归解决方案?但这将非常非常棘手,很可能是不可能的。例如,请查看此处:http://ideone.com/rH1keq。 [[1, 2, 3],0]'list_4':[[1, 2, 3],0]是两个单独的条目,但实际上是相同的引用。有'foo':[1, 2, 3],但是谁包含foo?最后对于插槽,它只是说:<__main__.A object at 0x2ae6efcf3ca8>。 - Ashwini Chaudhary
显示剩余6条评论
2个回答

5

对于全局变量,您可以这样做:

def magic_method(obj):
    return [name for name, val in globals().items() if val is obj]

如果你还想要本地名称,你可以使用 inspect 模块:
def magic_method(obj):
    import inspect
    frame = inspect.currentframe()
    try:
        names = [name for name, val in frame.f_back.f_locals.items() if val is obj]
        names += [name for name, val in frame.f_back.f_globals.items()
                  if val is obj and name not in names]
        return names
    finally:
        del frame

然后:

list_1 = [1, 2, 3]
list_2 = list_1

def my_fun():
    list_3 = list_1
    list_2 = list_1
    print(magic_method(list_1))

my_fun()
>>> ['list_3', 'list_1', 'list_2']

@cᴏʟᴅsᴘᴇᴇᴅ 我已更新答案,包括本地变量。 - jdehesa
1
请注意,这仅适用于调用magic_method的函数中的局部变量。如果调用堆栈上还有更多函数,则它们将被忽略。您可以循环遍历调用堆栈,直到frame.f_back返回None - Aran-Fey
@Rawing 是的,你说得对,我假设只有直接调用者的本地人才是感兴趣的,但你也可以像那样检查整个堆栈。 - jdehesa
如果您调用magic_method()函数,它会返回环境中的所有全局方法吗? - anitasp
@anitasp 你的意思是像magic_method()这样没有参数吗?那是不行的,因为函数按照它的写法需要一个参数。你所说的“环境中所有全局方法”是什么意思? - jdehesa

-2

这个有效:

def magic_method(var):
     names = filter(lambda x: globals()[x] is var, globals().keys())
     return names

is 执行引用比较。如果您正在使用 Python3,请将 list(...) 添加到结果表达式中。


应该使用 is 而不是 == - Antti Haapala -- Слава Україні
好的,它们不是同一个引用,但是它们具有相同的值,将“==”更改为“is”以获取引用。 - Radek Hofman
1
问题是关于同一对象的。两张不同的100美元钞票不是同一张纸币。 - Antti Haapala -- Слава Україні

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接