Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 4

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

Ответ 5

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

def f(a):
    return a

b = "x"
c = b
d = f(c)

e = [f(b), f(c), f(d)]

Что должно вернуть name(e[2]) и почему?

Ответ 6

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

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

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

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

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

Ответ 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

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

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

funcs.py:

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

main.py:

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

Ответ 9

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

fun_dict = {'fun1': fun1,
            'fun2': fun2,
            'fun3': fun3}

r_dict = dict(zip(fun_dict.values(), fun_dict.keys()))

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

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

Ответ 10

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

Ответ 11

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

Ответ 12

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

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

Короче говоря, вы, вероятно, могли бы использовать модуль проверки, чтобы получить обоснованное предположение о том, какой он есть, но вам, вероятно, нужно будет знать, какой кадр вы работаете/переходите по стеку, чтобы найти правильный. Но мне не хотелось бы представлять себе, насколько весело это будет пытаться разобраться с кодом 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()

Ответ 13

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

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

  def __unicode__(self):
    return self.name

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

Ответ 14

Вот мой ответ, я также использую 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 ok
    'objC'
    >>>

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

Ответ 15

У 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, который вы хотите искать имена, которые указывают на данный объект. Очевидно, что этот поиск может быть медленным для очень больших пространств имен, потому что они должны быть пройдены полностью.