我如何获取一个对象的名称?
- 2025-02-13 08:36:00
- admin 原创
- 39
问题描述:
假设我有如下代码:
x = 0
y = 1
z = 2
my_list = [x, y, z]
for item in my_list:
print("handling object ", name(item)) # <--- what would go instead of `name`?
如何在 Python 中获取每个对象的名称?也就是说:我可以name
在这段代码中写什么来代替,以便循环显示handling object x
然后handling object y
和handling object z
?
在我的实际代码中,我有一个函数字典,稍后我将在使用用户输入查找它们后调用它们:
def fun1():
pass
def fun2():
pass
def fun3():
pass
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
# suppose that we get the name 'fun3' from the user
fun_dict['fun3']()
如何fun_dict
自动创建,而不用写两次函数名?我希望能够写类似
fun_list = [fun1, fun2, fun3] # and I'll add more as the need arises
fun_dict = {}
for t in fun_list:
fun_dict[name(t)] = t
以避免重复名称。
解决方案 1:
在 Python 中对象不一定有名称,因此你无法获取名称。
当您创建一个变量时(如上所示x, y, z
),这些名称仅充当对象的“指针”或“引用”。对象本身并不知道您为其使用了什么名称,并且您无法轻松(如果有的话)获取对该对象的所有引用的名称。
但是,对象拥有属性并不罕见__name__
。函数确实有属性__name__
(除非它们是lambda 表达式),因此我们可以fun_dict
通过以下方式构建:
fun_dict = {t.__name__: t for t in fun_list)
解决方案 2:
这实际上是不可能的,因为可能有多个变量具有相同的值,或者一个值可能没有变量,或者一个值可能恰好具有与变量相同的值。
如果你真的想这样做,你可以使用
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
解决方案 3:
正如其他人提到的,这是一个非常棘手的问题。解决方案并不是“一刀切”,甚至远远不是。难度(或容易程度)实际上取决于您的情况。
我多次遇到过这个问题,但最近一次是在创建一个调试函数时。我希望该函数将一些未知对象作为参数并打印其声明的名称和内容。获取内容当然很容易,但声明的名称则是另一回事。
以下是我所想到的一些内容。
返回函数名称
确定函数的名称非常容易,因为它具有包含函数声明名称的__name__属性。
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
,name_of_function(copy_function)
它将返回test_function。
返回第一个匹配的对象名称
检查对象是否具有name属性,如果有则返回该属性(仅限声明函数)。请注意,您可以删除此测试,因为名称仍将保留在 中
globals()
。将 arg 的值与项中的值进行比较
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
返回所有匹配的对象名称
将 arg 的值与项的值进行比较
globals()
,并将名称存储在列表中。请注意,我过滤掉了以“_”开头的名称。
结果将由一个列表(用于多个匹配)、一个字符串(用于单个匹配)组成,否则为 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
解决方案 4:
这一行代码适用于所有类型的对象,只要它们在globals()
字典中,它们应该是:
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
解决方案 5:
如果您要获取在解释器中定义的函数或 lambda 或其他类似函数的对象的名称,则可以使用dill.source.getname
from 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'
解决方案 6:
使用反向字典。
fun_dict = {'fun1': fun1,
'fun2': fun2,
'fun3': fun3}
r_dict = dict(zip(fun_dict.values(), fun_dict.keys()))
反向字典会将每个函数引用映射到您在 fun_dict 中为其指定的确切名称,该名称可能是也可能不是您定义函数时使用的名称。而且,这种技术可以推广到其他对象,包括整数。
为了更加有趣和疯狂,您可以将正向和反向值存储在同一个字典中。如果您将字符串映射到字符串,我不会这样做,但如果您正在执行函数引用和字符串之类的操作,那就不太疯狂了。
解决方案 7:
请注意,尽管如上所述,对象通常不知道也无法知道与它们绑定的变量,但用 定义的函数def
在__name__
属性中确实有名称(在 中使用的名称def
)。此外,如果函数在同一个模块中定义(如您的示例所示),则将globals()
包含您想要的字典的超集。
def fun1:
pass
def fun2:
pass
def fun3:
pass
fun_dict = {}
for f in [fun1, fun2, fun3]:
fun_dict[f.__name__] = f
解决方案 8:
这是另一种思考方式。假设有一个name()
函数返回其参数的名称。给出以下代码:
def f(a):
return a
b = "x"
c = b
d = f(c)
e = [f(b), f(c), f(d)]
应该name(e[2])
返回什么?为什么?
解决方案 9:
我之所以想要有函数名称是因为我想在创建时
fun_dict
不用写两次函数名称,因为这似乎是创建错误的好方法。
为此,您可以使用一个很棒的getattr
函数,它允许您通过已知名称获取对象。因此,您可以这样做:
funcs.py:
def func1(): pass
def func2(): pass
main.py:
import funcs
option = command_line_option()
getattr(funcs, option)()
解决方案 10:
我知道这是迟来的回答。
要获取函数名称,您可以使用
func.__name__
name
获取没有或方法的任何 Python 对象的名称__name__
。您可以迭代其模块成员。
前任:。
# 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 name
性能说明:不要在大型模块中使用它。
解决方案 11:
变量名可以在 globals() 和 locals() 字典中找到。但它们不会提供您在上面寻找的内容。“bla”将包含 my_list 中每一项的值,而不是变量。
解决方案 12:
通常,当您想要执行此类操作时,您会创建一个类来保存所有这些函数,并使用一些清晰的前缀cmd_
或类似名称来命名它们。然后,您从命令中获取字符串,并尝试从带有前缀的类中获取该属性cmd_
。现在,您只需向类添加一个新函数/方法,它就可以供调用者使用。并且您可以使用文档字符串自动创建帮助文本。
正如其他答案所述,您可能能够使用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()
解决方案 13:
当我思考同样的问题时,我偶然发现了这个页面。
正如其他人所指出的,只需__name__
从函数中获取属性即可确定函数的名称,这很简单。对于没有合理方法确定的对象__name__
,即基本/原始对象(如 basestring 实例、int、long 等),这稍微有点棘手。
长话短说,您可能可以使用检查模块来猜测它是哪一个,但您可能必须知道您正在处理/遍历堆栈中的哪个框架才能找到正确的框架。但我不敢想象处理 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']
[]
%
再次输入我的姓名.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()
解决方案 14:
你定义一个class
并添加Unicode私有函数插入class
类似
class example:
def __init__(self, name):
self.name = name
def __unicode__(self):
return self.name
当然,您必须添加额外的变量self.name
,即对象的名称。
解决方案 15:
这是我的答案,我也在使用 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'
>>>
希望这能有所帮助。
解决方案 16:
根据您要尝试执行的操作,您可以使用这种方法。
就你的情况而言,你的函数将全部位于模块 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())()
解决方案 17:
Python 具有映射到哈希映射(称为命名空间)中的对象的名称。在任何时间点,一个名称始终只引用一个对象,但单个对象可以由任意数量的名称引用。给定一个名称,哈希映射可以非常高效地查找该名称所引用的单个对象。但是,给定一个对象(如上所述,它可以由多个名称引用),则没有有效的方法来查找引用它的名称。您需要做的是遍历命名空间中的所有名称并分别检查每个名称,看看它是否映射到给定的对象。这可以通过列表推导轻松完成:
[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
您想要搜索指向给定对象的名称的任何内容。显然,对于非常大的命名空间,这种搜索可能会很慢,因为必须完整地遍历它们。
解决方案 18:
你可以尝试
_ = [print(type(e).__name__) for e in entities]
用于对象集合entities
。
解决方案 19:
你好,有一种方法可以获取存储类实例的变量名称,那就是使用
当地人()
函数,它返回一个包含变量名称(字符串)及其值的字典
解决方案 20:
它不仅可以传递 val,还可以传递 name 和 val 的数组。例如
x = [name, val]
y = [name2, val2]
this = [x, y]
for i in this:
name = i[0]