Имена объектов в списке?

#python #list #introspection

#python #Список #самоанализ

Вопрос:

Я пытаюсь итеративно записывать словари в файл, но у меня возникают проблемы с созданием уникальных имен файлов для каждого dict.

 def variable_to_value(value):
    for n, v in globals().items():
        if v == value:
            return n
    else: 
        return None

a = {'a': [1,2,3]}
b = {'b': [4,5,6]}
c = {'c': [7,8,9]}

for obj in [a, b, c]:
    name = variable_to_value(obj)
    print(name)
  

Это выводит:

 a
obj
obj
  

Как я могу получить доступ к имени самого исходного объекта вместо obj ?

Комментарии:

1. Я в замешательстве, как a печатается

2. Что вы имеете в виду, когда говорите «имя объекта»? Что вы ожидаете увидеть?

3. @cricket_007 Вероятно, потому, что порядок dict.items не определен и variable_to_value возвращает имя первой соответствующей переменной, которую он находит. В моей системе я получаю a , b , и c .

Ответ №1:

Проблема в том obj , что ваша переменная итерации также globals включена. Получаете ли вы a или obj просто по счастливой случайности. Вы не можете решить проблему в целом, потому что объект может иметь любое количество назначений в глобалах. Вы могли бы обновить свой код, чтобы исключить известные ссылки, но это очень хрупко.

Например

 a = {'a': [1,2,3]}
b = {'b': [4,5,6]}
c = {'c': [7,8,9]}

print("'obj' is also in globals")

def variable_to_value(value):
    return [n for n,v in globals().items() if v == value]

for obj in [a, b, c]:
    name = variable_to_value(obj)
    print(name)

print("you can update your code to exclude it")

def variable_to_value(value, exclude=None):
    return [n for n,v in globals().items() if v == value and n != exclude]

for obj in [a, b, c]:
    name = variable_to_value(obj, 'obj')
    print(name)

print("but you'll still see other assignments")

foo = a
bar = b
bax = c

for obj in [a, b, c]:
    name = variable_to_value(obj, 'obj')
    print(name)
  

При запуске

 'obj' is also in globals
['a', 'obj']
['b', 'obj']
['c', 'obj']
you can update your code to exclude it
['a']
['b']
['c']
but you'll still see other assignments
['a', 'foo']
['b', 'bar']
['c', 'bax']
  

Ответ №2:

Функция возвращает первое найденное имя, ссылающееся на объект в вашем globals() . Однако на каждой итерации имя obj будет ссылаться на каждый из объектов. Таким a b образом, либо c возвращается имя, либо obj , в зависимости от того, которое было достигнуто первым globals() .

Вы можете избежать возврата obj , исключив это имя из поиска в вашей функции — своего рода хакерство:

 def variable_to_value(value):
    for n, v in globals().items():
        if v == value and n != 'obj':
            return n
    else: 
        return None
  

Комментарии:

1. Это делает результат функции зависящим от того, что ее вызывает. (Например, это не сработает, если внешний вид OP использовал «my_obj» в качестве имени итерации вместо «obj».) Функции должны работать не так.

2. @acdr Это четко указано как хакерский подход . Вряд ли стоит возиться с именами в первую очередь

Ответ №3:

Python на самом деле так не работает.

Объекты в Python не имеют врожденных имен. Это имена, которые принадлежат объекту, а не наоборот: у объекта может быть много имен (или вообще нет имен).

Вы получаете две копии «obj», напечатанные, потому что во время вызова variable_to_value и имя b , и имя obj относятся к одному и тому же объекту! (Словарь {'b': [4,5,6]} ) Поэтому, когда вы ищете глобальное пространство имен для любого значения, равного obj (обратите внимание, что вы должны проверять использование is , а не == ), это фактически случайно, получаете ли вы b или obj .

Комментарии:

1. Побочный вопрос: зачем использовать is вместо == ?

2. == проверяет эквивалентность, а не идентичность. Например a = 1000 , b=1000 , a==b возвращает True , но a is b возвращает False . Это не один и тот же объект, они просто эквивалентны.

Ответ №4:

Итак, вы хотите найти имя любого объекта, доступного в globals() ?

Внутри for цикла globals() dict происходит мутация, добавление obj в его пространство имен. Итак, на втором проходе у вас есть две ссылки на один и тот же объект (первоначально на него ссылается только имя ‘a’).

Опасность использования globals() , я полагаю.