Python: функция, которая возвращает dict, ключи которого являются именами входных аргументов - PullRequest
2 голосов
/ 06 марта 2012

Можно ли написать функцию f, которая принимает произвольный набор смешанных данных:

T = 1.0
N = 20
L = 10
args = (T,N,L)

f(*args) # or maybe f(T,N,L)?

и возвращает в качестве вывода:

{'T':1.0, 'N':20, 'L':10}

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

Продолжение: Python: Использование фиктивного класса для передачи имен переменных?

Ответы [ 6 ]

3 голосов
/ 06 марта 2012

Нет, это вообще невозможно с *args.Вам придется использовать ключевые аргументы:

>>> def f(**kwargs):
...  return kwargs
... 
>>> f(T=1.0, N=20, L=10)
{'T': 1.0, 'L': 10, 'N': 20}

Причина в том, что *args не вводит имена для отдельных аргументов;это только вводит имя args для всего их списка.Функция не имеет представления о том, какие имена, если они есть, имеют аргументы вне ее.

Когда число аргументов фиксировано, вы можете сделать это с помощью locals:

>>> def g(T, N, L):
...  return locals()
... 
>>> g(T=1.0, N=20, L=10)
{'L': 10, 'T': 1.0, 'N': 20}

(или явно с return {'T': T, 'N': N, 'L': L}.)

2 голосов
/ 06 марта 2012

Ваша догадка, к сожалению, неверна, и фактически весь вопрос выдает неверное понимание того, как работают имена Python.

Объекты Python, в общем, не знают своих имен. Это вполне понятно, если учесть, что вы можете легко назначить a=b, и теперь a и b оба ссылаются на один и тот же объект. «Переменные» Python - это просто имена, которые указывают на объекты, они не содержат эти объекты в реальном смысле. Когда вы передаете аргументы функции, вы передаете базовые объекты, а не имена. Принимающая функция просто связывает их с именами, указанными в сигнатуре функции, или, в вашем случае, просто сохраняет их в args, не называя их вообще.

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

2 голосов
/ 06 марта 2012

В Python переменные - это просто метки, прикрепленные к значениям.Таким образом, из другой области невозможно узнать, какие метки вы использовали при вызове функции.

1 голос
/ 06 марта 2012

Решение с использованием globals().Это будет работать только в том случае, если значения являются уникальными в области видимости модуля, поэтому оно хрупкое - если есть дубликаты, он выберет первое имя , которое указывает на это значение несколько произвольно.И да, вам, вероятно, лучше не делать этого в любом случае и вместо этого переосмыслить проблему.

def f(*names):
    r = {}
    for n in names:
        r[[ name for name in globals() if globals()[name] is n ][0]] = n
    return r

T = 1.0
N = 20
L = 10

print f(T,N,L)
{'T': 1.0, 'L': 10, 'N': 20}
0 голосов
/ 06 марта 2012

Необходимо передать ключи и значения в качестве отдельных аргументов:

keys = ('T', 'N', 'L')
values = (1.0, 20, 10)
d = dict(zip(keys, values))

В вашем коде строка args = (T,N,L) вычисляетargs = (1.0, 20, 10), имена переменных T, N, L заменяются их значениями.

0 голосов
/ 06 марта 2012

Да, насколько я знаю, args - это список.Чтобы сохранить имена меток, вам нужно передать dict ** kwargs и явно или программно установить имена, используя local.

. Вы можете сделать что-то вроде:

def filter_locals(caller_locals, *args):
    filtered = {}
    for key in args:
        filtered[key] = caller_locals[key]
    return filtered

Тогда:

X = 1
Y = 2
func(filter_locals(locals(), 'X', 'Y')

Где func обрабатывает список произвольной длины как kwargs.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...