有没有办法在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
修改:某些背景信息:
我实际上在做的是创建一个我可以通过命令行指定的函数列表。
我有:
def fun1:
pass
def fun2
pass
def fun3:
pass
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
我从命令行获取该函数的名称,我想调用相关函数:
func_name = parse_commandline()
fun_dict[func_name]()
我想要拥有该函数名称的原因是因为我想创建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
这样我只需要写一次函数名。
答案 0 :(得分:27)
对象不一定在python中有名字,所以你不能得到这个名字。
对象在具有名称的情况下具有__name__
属性并不罕见,但这不是标准python的一部分,并且大多数内置类型没有。
当您创建变量(如上面的x,y,z)时,这些名称只是充当对象的“指针”或“引用”。对象本身不知道您使用的是什么名称,并且您不能轻易地(如果有的话)获取该对象的所有引用的名称。
更新:但是,函数确实有__name__
(除非它们是lambda),所以在这种情况下你可以这样做:
dict([(t.__name__, t) for t in fun_list])
答案 1 :(得分:11)
这实际上是不可能的,因为可能有多个变量具有相同的值,或者某个值可能没有变量,或者某个值可能只是偶然的变量值。
如果您真的想这样做,可以使用
def variable_for_value(value):
for n,v in globals().items():
if v == value:
return n
return None
但是,如果您首先迭代名称会更好:
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
答案 2 :(得分:6)
如果您想获取函数或lambda的名称或解释器中定义的其他类似函数的对象,可以使用dill
中的dill.source.getname
。它几乎寻找__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'
答案 3 :(得分:5)
这种单行程适用于所有类型的对象,只要它们在globals()
dict中,它们应该是:
def name_of_global_obj(xx):
return [objname for objname, oid in globals().items()
if id(oid)==id(xx)][0]
或等同于:
def name_of_global_obj(xx):
for objname, oid in globals().items():
if oid is xx:
return objname
答案 4 :(得分:2)
这是考虑它的另一种方式。假设有name()
函数返回其参数的名称。给出以下代码:
def f(a):
return a
b = "x"
c = b
d = f(c)
e = [f(b), f(c), f(d)]
name(e[2])
应该返回什么,以及为什么?
答案 5 :(得分:2)
正如其他人所说,这是一个非常棘手的问题。对此的解决方案不是“一刀切”,甚至远程也不是。困难(或缓解)实际上取决于你的情况。
我已经多次遇到过这个问题,但最近在创建调试功能时。我希望函数将一些未知对象作为参数并打印它们声明的名称和内容。当然,获取内容很容易,但声明的名称是另一个故事。
以下是我提出的一些内容。
确定函数的名称非常简单,因为它具有包含函数声明名称的 __ name __ 属性。
my $sum_xx = sum map { $_ * $_ } @x;
举个例子,如果您创建函数name_of_function = lambda x : x.__name__
def name_of_function(arg):
try:
return arg.__name__
except AttributeError:
pass`
,然后def test_function(): pass
,然后copy_function = test_function
,它将返回 test_function 。
检查对象是否具有 __ name __ 属性,如果是,则返回它(仅声明函数)。请注意,您可以删除此测试,因为该名称仍位于name_of_function(copy_function)
。
将arg的值与globals()
中的项值进行比较,并返回第一个匹配项的名称。请注意,我正在过滤掉以“_”开头的名称。
结果将包含第一个匹配对象的名称,否则为None。
globals()
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
中的项目值和列表中的商店名称进行比较。请注意,我正在过滤掉以“_”开头的名称。结果将包含一个列表(用于多个匹配),一个字符串(用于单个匹配),否则为None。当然,您应该根据需要调整此行为。
globals()
答案 6 :(得分:1)
我想要拥有该函数名称的原因是因为我想创建
fun_dict
而不编写两次函数的名称,因为这似乎是创建错误的好方法。
为此,您有一个很棒的getattr
函数,它允许您通过已知名称获取对象。所以你可以这样做:
funcs.py:
def func1(): pass
def func2(): pass
main.py:
import funcs
option = command_line_option()
getattr(funcs, option)()
答案 7 :(得分:1)
使用反向字典。
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
r_dict = dict(zip(fun_dict.values(), fun_dict.keys()))
反向dict会将每个函数引用映射到fun_dict中给出的确切名称,这可能是您定义函数时使用的名称,也可能不是。而且,这种技术可以推广到其他对象,包括整数。
为了获得额外的乐趣和精神错乱,您可以将正向和反向值存储在同一个词典中。如果你将字符串映射到字符串,我不会这样做,但如果你正在做类似函数引用和字符串的事情,那就不会太疯狂了。
答案 8 :(得分:1)
请注意,虽然如上所述,对象通常不会也无法知道哪些变量绑定到它们,但使用def
定义的函数在__name__
属性中具有名称(def
属性中使用的名称{1}})。此外,如果函数在同一模块中定义(如示例中所示),则globals()
将包含所需字典的超集。
def fun1:
pass
def fun2:
pass
def fun3:
pass
fun_dict = {}
for f in [fun1, fun2, fun3]:
fun_dict[f.__name__] = f
答案 9 :(得分:0)
通常,当您想要执行此类操作时,您可以创建一个类来保存所有这些函数,并使用一些明确的前缀cmd_
等命名它们。然后从命令中获取字符串,并尝试从具有cmd_
前缀的类中获取该属性。现在,您只需要向类中添加一个新的函数/方法,它就可供您的调用者使用。您可以使用doc字符串自动创建帮助文本。
如其他答案中所述,您可以使用globals()
和模块中的常规功能执行相同的操作,以更贴近您要求的内容。
这样的事情:
class Tasks:
def cmd_doit(self):
# do it here
func_name = parse_commandline()
try:
func = getattr('cmd_' + func_name, Tasks())
except AttributeError:
# bad command: exit or whatever
func()
答案 10 :(得分:0)
变量名可以在globals()和locals()中找到。但他们不会给你上面你想要的东西。 “bla”将包含my_list的每个项目的值,而不是变量。
答案 11 :(得分:0)
我在讨论同样的问题时遇到了这个页面。
正如其他人所说,只需从函数中获取__name__
属性就可以确定函数的名称。对于没有合理的方法来确定__name__
,即基本/原始对象,如基本字符串实例,整数,长整数等,这一点稍微有点棘手。
长话短说,您可以使用检查模块对其中的哪一个做出有根据的猜测,但您可能必须知道您正在使用哪个框架/遍历堆栈以找到正确的框架。但是我不想想这会有多大的乐趣来处理eval / exec代码。
% python2 whats_my_name_again.py
needle => ''b''
['a', 'b']
[]
needle => '<function foo at 0x289d08ec>'
['c']
['foo']
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
needle => '<__main__.a_class instance at 0x289d3aac>'
['e', 'd']
[]
needle => '<function bar at 0x289d0bfc>'
['f', 'bar']
[]
%
whats_my_name_again.py:
#!/usr/bin/env python
import inspect
class a_class:
def __init__(self):
pass
def foo():
def bar():
pass
a = 'b'
b = 'b'
c = foo
d = a_class()
e = d
f = bar
#print('globals', inspect.stack()[0][0].f_globals)
#print('locals', inspect.stack()[0][0].f_locals)
assert(inspect.stack()[0][0].f_globals == globals())
assert(inspect.stack()[0][0].f_locals == locals())
in_a_haystack = lambda: value == needle and key != 'needle'
for needle in (a, foo, bar, d, f, ):
print("needle => '%r'" % (needle, ))
print([key for key, value in locals().iteritems() if in_a_haystack()])
print([key for key, value in globals().iteritems() if in_a_haystack()])
foo()
答案 12 :(得分:0)
您定义class
并添加Unicode私有函数,插入class
class example:
def __init__(self, name):
self.name = name
def __unicode__(self):
return self.name
当然,您必须添加额外的变量self.name
,这是对象的名称。
答案 13 :(得分:0)
这是我的答案,我也在使用globals()。items()
def get_name_of_obj(obj, except_word = ""):
for name, item in globals().items():
if item == obj and name != except_word:
return name
我添加了except_word,因为我想过滤掉for循环中使用的一些单词。 如果你没有添加它,for循环中的关键字可能会混淆这个函数,有时在函数结果中可能会出现以下情况中的“each_item”这样的关键字,取决于你对循环做了什么。
例如
for each_item in [objA, objB, objC]:
get_name_of_obj(obj, "each_item")
例如
>>> objA = [1, 2, 3]
>>> objB = ('a', {'b':'thi is B'}, 'c')
>>> for each_item in [objA, objB]:
... get_name_of_obj(each_item)
...
'objA'
'objB'
>>>
>>>
>>> for each_item in [objA, objB]:
... get_name_of_obj(each_item)
...
'objA'
'objB'
>>>
>>>
>>> objC = [{'a1':'a2'}]
>>>
>>> for item in [objA, objB, objC]:
... get_name_of_obj(item)
...
'objA'
'item' <<<<<<<<<< --------- this is no good
'item'
>>> for item in [objA, objB]:
... get_name_of_obj(item)
...
'objA'
'item' <<<<<<<<--------this is no good
>>>
>>> for item in [objA, objB, objC]:
... get_name_of_obj(item, "item")
...
'objA'
'objB' <<<<<<<<<<--------- now it's ok
'objC'
>>>
希望这可以提供帮助。
答案 14 :(得分:0)
Python的名称映射到称为名称空间的哈希图中的对象。在任何时间,名称始终始终恰好指向一个对象,但是单个对象可以由任意数量的名称引用。给定一个名称,哈希表查找该名称所指的单个对象非常有效。但是,给定一个 object ,正如前面提到的,可以用多个名称来引用,没有一种有效的方法来查找引用该名称的名称。您要做的是遍历命名空间中的所有名称,并分别检查每个名称,然后查看它是否映射到给定的对象。列表理解很容易做到这一点:
[k for k,v in locals().items() if v is myobj]
这将得出包含当前映射到对象myobj
的所有本地“变量”名称的字符串列表。
>>> a = 1
>>> this_is_also_a = a
>>> this_is_a = a
>>> b = "ligma"
>>> c = [2,3, 534]
>>> [k for k,v in locals().items() if v is a]
['a', 'this_is_also_a', 'this_is_a']
当然,locals()
可以替换为您要搜索指向给定对象的名称的任何dict
。显然,对于很大的名称空间,此搜索可能会很慢,因为必须完整遍历它们。
答案 15 :(得分:0)
根据您要尝试执行的操作,可以使用this方法。
在您的情况下,所有功能都将存在于模块foo中。然后您可以:
import foo
func_name = parse_commandline()
method_to_call = getattr(foo, func_name)
result = method_to_call()
或更简洁地说:
import foo
result = getattr(foo, parse_commandline())()
答案 16 :(得分:0)
我知道这是迟到的答案。
func.__name__
name
或 __name__
方法的 Python 对象的名称。您可以迭代其模块成员。例如:.
# package.module1.py
obj = MyClass()
# package.module2.py
import importlib
def get_obj_name(obj):
mod = Obj.__module__ # This is necessary to
module = module = importlib.import_module(mod)
for name, o in module.__dict__.items():
if o == obj:
return o
性能说明:不要在大型模块中使用它。