【问题标题】:Names of objects in a list?列表中对象的名称?
【发布时间】:2016-10-05 15:00:21
【问题描述】:

我正在尝试将字典迭代地写入文件,但在为每个字典创建唯一文件名时遇到问题。

def variable_to_value(value):
    for n, v in globals().items():
        if v == value:
            return n
    else: 
        return None

a = {'a': [1,2,3]}
b = {'b': [4,5,6]}
c = {'c': [7,8,9]}

for obj in [a, b, c]:
    name = variable_to_value(obj)
    print(name)

打印出来:

a
obj
obj

如何访问原始对象本身的名称而不是obj

【问题讨论】:

  • 我很困惑a 的打印方式
  • 您说的“对象名称”是什么意思?您希望看到什么?
  • @cricket_007 可能是因为dict.items 的顺序未定义,而variable_to_value 返回它找到的第一个匹配变量的名称。在我的系统上,我得到了abc

标签: python list introspection


【解决方案1】:

问题是obj,你的迭代变量也在globals。无论您获得a 还是obj 都只是运气。你一般不能解决这个问题,因为一个对象可以在全局变量中有任意数量的赋值。您可以更新代码以排除已知引用,但这非常脆弱。

例如

a = {'a': [1,2,3]}
b = {'b': [4,5,6]}
c = {'c': [7,8,9]}

print("'obj' is also in globals")

def variable_to_value(value):
    return [n for n,v in globals().items() if v == value]

for obj in [a, b, c]:
    name = variable_to_value(obj)
    print(name)

print("you can update your code to exclude it")

def variable_to_value(value, exclude=None):
    return [n for n,v in globals().items() if v == value and n != exclude]

for obj in [a, b, c]:
    name = variable_to_value(obj, 'obj')
    print(name)

print("but you'll still see other assignments")

foo = a
bar = b
bax = c

for obj in [a, b, c]:
    name = variable_to_value(obj, 'obj')
    print(name)

运行时

'obj' is also in globals
['a', 'obj']
['b', 'obj']
['c', 'obj']
you can update your code to exclude it
['a']
['b']
['c']
but you'll still see other assignments
['a', 'foo']
['b', 'bar']
['c', 'bax']

【讨论】:

    【解决方案2】:

    该函数返回它找到引用globals() 中的对象的第一个名称。但是,在每次迭代中,名称 obj 将引用每个对象。因此,要么返回名称 abc,要么返回 obj,这取决于在 globals() 中首先到达的名称。

    您可以通过在函数的搜索中排除该名称来避免返回 obj - 有点骇人听闻

    def variable_to_value(value):
        for n, v in globals().items():
            if v == value and n != 'obj':
                return n
        else: 
            return None
    

    【讨论】:

    • 这使得函数的结果取决于调用它的内容。 (例如,如果 OP 的外观使用“my_obj”作为迭代名称而不是“obj”,它将无法工作。)这不是函数应该如何工作的。
    • @acdr 明确表示为 hackish 方法。一开始就不应该摆弄名字
    【解决方案3】:

    Python 实际上并不是这样工作的。

    Python 中的对象没有天生的名称。它是属于一个对象的名称,而不是相反:一个对象可以有多个名称(或根本没有名称)。

    您将打印两个“obj”副本,因为在您调用variable_to_value 时,名称b 和名称obj 指的是同一个对象! (字典{'b': [4,5,6]})因此,当您在全局命名空间中搜索等于obj 的任何值时(请注意,您应该使用is 而不是== 进行检查)无论您是否得到,它实际上都是随机的bobj

    【讨论】:

    • 附带问题:为什么使用is 而不是==
    • == 检查等价性,而不是身份。例如。 a = 1000b=1000a==b 返回 True,但 a is b 返回 False。它们不是同一个对象,它们只是等价的。
    【解决方案4】:

    所以您想在globals() 中找到任何可用对象的名称?

    for 循环内,globals() dict 正在发生变异,在其命名空间中添加obj。因此,在您的第二次传递中,您有两个对同一个对象的引用(最初仅由名称“a”引用)。

    我想,使用globals() 很危险。

    【讨论】:

      猜你喜欢
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多