Как я могу получить имя объекта в Python?

Есть ли способ получить имя объекта в 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 

Таким образом, мне нужно только написать имена функций один раз.

14 Solutions collect form web for “Как я могу получить имя объекта в Python?”

Объекты не обязательно имеют имена в python, поэтому вы не можете получить имя. Для объектов нет атрибута __name__ в тех случаях, когда у них есть имя, но это не входит в стандартный питон, и большинство встроенных типов их не имеют.

Когда вы создаете переменную, такую ​​как x, y, z выше, эти имена просто действуют как «указатели» или «ссылки» на объекты. Сами объекты не знают, какие имена вы используете для него, и вы не можете легко (если вообще) получить имена всех ссылок на объект.

Обновление. Однако функции имеют __name__ (если только они не являются лямбдами), поэтому в этом случае вы можете:

 dict([(t.__name__, t) for t in fun_list]) 

Это действительно невозможно, так как может быть несколько переменных, имеющих одно и то же значение, или значение не может иметь никакой переменной, или значение может иметь одно и то же значение как переменная только случайно.

Если вы действительно хотите это сделать, вы можете использовать

 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 

Если вы хотите получить имена функций или лямбда или другие функциональноподобные объекты, которые определены в интерпретаторе, вы можете использовать dill.source.getname из 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' 

Этот однострочный слой работает для всех типов объектов, если они находятся в 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 

Как говорили другие, это очень сложный вопрос. Решения для этого не «подходят для всех», даже не отдаленно. Трудность (или легкость) действительно будет зависеть от вашей ситуации.

Я несколько раз сталкивался с этой проблемой, но совсем недавно при создании функции отладки. Я хотел, чтобы функция принимала некоторые неизвестные объекты в качестве аргументов и печатала их объявленные имена и содержимое. Получение содержимого легко, но объявленное имя – это еще одна история.

Ниже следует то, что я придумал.

Имя функции возврата

Определение имени функции очень просто, так как оно имеет атрибут __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 .

Вернуть первое совпадающее имя объекта

  1. Проверьте, имеет ли объект атрибут __name__ и возвращает его, если это так (только объявленные функции). Обратите внимание, что этот тест можно удалить, так как имя будет по-прежнему находиться в globals() .

  2. Сравните значение 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 

Обратите внимание, что пока, как отмечено, объекты вообще не знают и не могут знать, какие переменные связаны с ними, функции, определенные с 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 

Вот еще один способ подумать об этом. Предположим, что существует функция name() которая возвращает имя своего аргумента. Учитывая следующий код:

 def f(a): return a b = "x" c = b d = f(c) e = [f(b), f(c), f(d)] 

Что следует name(e[2]) , и почему?

И причина, по которой я хочу иметь имя функции, заключается в том, что я хочу создать fun_dict не записывая имена функций дважды, поскольку это похоже на хороший способ создания ошибок.

Для этого у вас есть замечательная функция getattr , которая позволяет вам получить объект по известному имени. Таким образом, вы можете сделать, например:

funcs.py:

 def func1(): pass def func2(): pass 

main.py:

 import funcs option = command_line_option() getattr(funcs, option)() 

Используйте обратный dict.

 fun_dict = {'fun1': fun1, 'fun2': fun2, 'fun3': fun3} r_dict = dict(zip(fun_dict.values(), fun_dict.keys())) 

Обратный dict будет отображать каждую функцию ссылки на точное имя, которое вы дали ему в fun_dict, который может быть или не быть именем, которое вы использовали, когда вы определили функцию. И эта техника обобщается на другие объекты, включая целые числа.

Для дополнительного удовольствия и безумия вы можете сохранить прямые и обратные значения в одном и том же dict. Я бы не сделал этого, если бы вы отображали строки в строки, но если вы делаете что-то вроде ссылок на функции и строк, это не слишком сумасшествие.

Вот мой ответ, я также использую 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. Если вы его не добавили, ключевое слово in for loop может смутить эту функцию, иногда ключевое слово типа «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' >>> 

Надеюсь, это поможет.

Имена переменных можно найти в файлах globals () и locals (). Но они не дадут вам то, что вы ищете выше. «bla» будет содержать значение каждого элемента my_list, а не переменной.

Обычно, когда вы хотите сделать что-то подобное, вы создаете класс для хранения всех этих функций и назовите их с помощью некоторого ясного префикса 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() 

Я столкнулся с этой страницей, задавая тот же вопрос.

Как отмечали другие, достаточно просто взять атрибут __name__ из функции, чтобы определить имя функции. Это немного сложнее с объектами, которые не имеют разумного способа определить __name__ , т. Е. Базовые / примитивные объекты, такие как экземпляры basestring, ints, longs и т. Д.

Короче говоря, вы, вероятно, могли бы использовать модуль проверки, чтобы получить обоснованное предположение о том, какой он есть, но вам, вероятно, нужно знать, какой кадр вы работаете / переходите по стеку, чтобы найти правильный. Но мне бы не хотелось представить, насколько это было бы весело, если бы он пытался справиться с кодом eval / exec'ed.

 % 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() 

Вы определяете class и добавляете частную функцию Unicode, вставляете class как

 class example: def __init__(self, name): self.name = name def __unicode__(self): return self.name 

Конечно, вам нужно добавить дополнительную переменную self.name которая является именем объекта.

  • Почему вызывается только одна функция flask teardown_request, когда представление вызывает исключение?
  • SQLAlchemy: Знание имен полей и значений объекта модели?
  • Не удалось получить файлы из send_from_directory () в колбе
  • Способ создания многострочных комментариев в Python?
  • Быстрая библиотека минимального потока для Python
  • Учебник Python Bottle: не может получить ничего из примера HelloWorld
  • Приложение Flask зависает при обработке запроса
  • Когда использовать возврат (что-то вывести)?
  • Python itertools - медленный?
  • Использование InitSpider с всплеском: только анализ страницы входа?
  • Убедитесь, что скрипт Python с субпроцессами умирает на SIGINT
  • Python - лучший язык программирования в мире.