如何在Python中获取对象的名称?

Nat*_*man 29 python introspection

有没有办法在Python中获取对象的名称?例如:

my_list = [x, y, z] # x, y, z have been previously defined

for bla in my_list:
    print "handling object ", name(bla) # <--- what would go instead of `name`?
    # do something to bla
Run Code Online (Sandbox Code Playgroud)

编辑:一些上下文:

我实际上在做的是创建一个我可以通过命令行指定的函数列表.

我有:

def fun1:
    pass
def fun2
    pass
def fun3:
    pass

fun_dict = {'fun1': fun1,
            'fun2': fun2,
            'fun3': fun3}
Run Code Online (Sandbox Code Playgroud)

我从命令行获取函数的名称,我想调用相关函数:

func_name = parse_commandline()

fun_dict[func_name]()
Run Code Online (Sandbox Code Playgroud)

我想拥有该函数名称的原因是因为我想创建fun_dict两次函数的名称,因为这似乎是创建错误的好方法.我想做的是:

fun_list = [fun1, fun2, fun3] # and I'll add more as the need arises

fun_dict = {}
[fun_dict[name(t) = t for t in fun_list] # <-- this is where I need the name function
Run Code Online (Sandbox Code Playgroud)

这样我只需要写一次函数名.

Len*_*bro 30

对象不一定在python中有名称,因此您无法获取名称.对象__name__在这些情况下具有属性并不常见,因为它们具有名称,但这不是标准python的一部分,并且大多数内置类型没有.

当您创建一个变量(如上面的x,y,z)时,这些名称就会充当对象的"指针"或"引用".对象本身不知道您使用的是什么名称,并且您不能轻易地(如果有的话)获取该对象的所有引用的名称.

更新:但是,函数确实有__name__(除非它们是lambdas)所以,在这种情况下你可以这样做:

dict([(t.__name__, t) for t in fun_list])
Run Code Online (Sandbox Code Playgroud)

  • @smci:假设对象在globals()中,它通常不是,并且它会对整数和许多字符串给出误报,当然忽略了许多对象在任何情况下都没有名称的事实所有.另外,你应该使用`is`. (6认同)
  • @smci:你错了:他们*没有*至少有一个名字.我在2009年10月的上面说过,我在22小时前和11小时前说过.老实说,现在是时候给你一分钱了:**对象不一定在Python中有一个名字**.好?这难以理解吗?他们还可以拥有*多于一个名称*,然后你会返回哪个名字?这里没有涉及别名. (6认同)
  • 学究的 prig,是的。辱骂?我只想说可能应该更好。 (3认同)
  • @smci:不,用户声明的对象至少没有一个名称.真.(你说的对象,而不是变量和Python中的"变量"这个词无论如何都不是真的有用.)这是一个例子:foo = [MyClass()].MyClass()实例的名称是什么?对,它没有名字.而666和id(666)就像用户声明的一样.你似乎充满了错误的假设.没有有用的通用方法可以在Python中找到对象的"名称",因为OBJECTS可能没有任何名称.真. (2认同)

Mar*_*wis 11

这实际上是不可能的,因为可能存在多个具有相同值的变量,或者值可能没有变量,或者值可能只是偶然地具有与变量相同的值.

如果你真的想这样做,你可以使用

def variable_for_value(value):
    for n,v in globals().items():
        if v == value:
            return n
    return None
Run Code Online (Sandbox Code Playgroud)

但是,如果你首先迭代名字会更好:

my_list = ["x", "y", "z"] # x, y, z have been previously defined

for name in my_list:
    print "handling variable ", name
    bla = globals()[name]
    # do something to bla
Run Code Online (Sandbox Code Playgroud)

 


Six*_*Six 11

正如其他人提到的,这是一个非常棘手的问题。解决这个问题的方法并不是“一刀切”,甚至远程解决方案也不是。困难(或容易)实际上取决于您的情况。

我曾多次遇到这个问题,但最近一次是在创建调试功能时。我希望该函数将一些未知对象作为参数并打印它们声明的名称和内容。获取内容当然很容易,但声明的名称则是另一回事了。

以下是我的一些想法。

返回函数名

确定函数的名称非常容易,因为它具有包含函数声明名称的__name__属性。

name_of_function = lambda x : x.__name__

def name_of_function(arg):
    try:
        return arg.__name__
    except AttributeError:
        pass`
Run Code Online (Sandbox Code Playgroud)

举个例子,如果你创建函数def test_function(): pass, then copy_function = test_function, then name_of_function(copy_function),它将返回test_function

返回第一个匹配的对象名称

  1. 检查对象是否具有__name__属性,如果有则返回它(仅限声明的函数)。请注意,您可以删除此测试,因为名称仍将位于globals().

  2. 将 arg 的值与 in 中的项目值进行比较globals(),并返回第一个匹配项的名称。请注意,我正在过滤掉以“_”开头的名称。

结果将包含第一个匹配对象的名称,否则为 None。

def name_of_object(arg):
    # check __name__ attribute (functions)
    try:
        return arg.__name__
    except AttributeError:
        pass

    for name, value in globals().items():
        if value is arg and not name.startswith('_'):
            return name
Run Code Online (Sandbox Code Playgroud)

返回所有匹配的对象名称

  • globals()将 arg 的值与列表中的项目值和存储名称进行比较。请注意,我正在过滤掉以“_”开头的名称。

结果将包含一个列表(对于多个匹配)、一个字符串(对于单个匹配),否则为 None。当然,您应该根据需要调整此行为。

def names_of_object(arg):
    results = [n for n, v in globals().items() if v is arg and not n.startswith('_')]
    return results[0] if len(results) is 1 else results if results else None
Run Code Online (Sandbox Code Playgroud)


smc*_*mci 6

这种单行代码适用于所有类型的对象,只要它们在命令中即可globals(),它们应该是:

def name_of_global_obj(xx):
    return [objname for objname, oid in globals().items()
            if id(oid)==id(xx)][0]
Run Code Online (Sandbox Code Playgroud)

或等效地:

def name_of_global_obj(xx):
    for objname, oid in globals().items():
        if oid is xx:
            return objname
Run Code Online (Sandbox Code Playgroud)


Mik*_*rns 6

如果要查找函数或lambda的名称或解释器中定义的其他类似函数的对象,可以使用dill.source.getnamefrom dill.它几乎寻找__name__方法,但在某些情况下,它知道如何找到名称的其他魔法...或对象的名称.我不想进入关于为python对象找到一个真实名称的争论,无论这意味着什么.

>>> from dill.source import getname
>>> 
>>> def add(x,y):
...   return x+y
... 
>>> squared = lambda x:x**2
>>> 
>>> print getname(add)
'add'
>>> print getname(squared)
'squared'
>>> 
>>> class Foo(object):
...   def bar(self, x):
...     return x*x+x
... 
>>> f = Foo()
>>> 
>>> print getname(f.bar)
'bar'
>>> 
>>> woohoo = squared
>>> plus = add
>>> getname(woohoo)
'squared'
>>> getname(plus)
'add'
Run Code Online (Sandbox Code Playgroud)