#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()
, я полагаю.