2016-09-07 1 views
1

Я использую django, но я думаю, что этот вопрос в первую очередь принадлежит самому Python.Использование названных аргументов как переменных

У меня есть что-то вроде:

def get(self, request, arg, *args, **kwargs): 

    if kwargs['m0'] == 'death': 
     if kwargs['m1'] == 'year': 
     result = Artists.objects.filter(death_year=arg) 
     elif kwargs['m1'] == 'month': 
     result = Artists.objects.filter(death_month=arg) 
     elif kwargs['m1'] == 'day': 
     result = Artists.objects.filter(death_day=arg) 
    elif kwargs['m0'] == 'birth': 
     if kwargs['m1'] == 'year': 
     result = Artists.objects.filter(birth_year=arg) 
     elif kwargs['m1'] == 'month': 
     result = Artists.objects.filter(birth_month=arg) 
     elif kwargs['m1'] == 'day': 
     result = Artists.objects.filter(birthh_day=arg) 

Где death_year именованный аргумент, что это поле в моей модели Artists, представляющий столбец в моей базе данных. Переменные «m0» и m1 передаются от urlconf к моей функции get (это фактически метод get в моем классе). Могу ли я контролировать значение имени переменной death_year без использования цепочки if else if (например, death_month или birth_year)? Поскольку у меня есть много вариантов, мне придется использовать нелепо очень длинную условную цепочку, которая ведет к этой же строке, но с другим именованным аргументом.

Я очень сомневаюсь, что вы должны понять всю эту проблему, чтобы ответить на вопрос. Исходный вопрос прост: могу ли я использовать именованный аргумент и его соответствующее значение как переменные в Python?

+4

У вас есть пример того, какое значение имеет значение 'arg'? 'Model.objects.filter (** dic)' отлично действует там, где 'dic = {'death_year': 'foo'}' – Sayse

+0

Спасибо @Sayse, я на самом деле пробовал это, но получил «Исключение типа: FieldError» «Исключение Значение: Невозможно разобрать запрос по ключевому слову в качестве dict. –

+0

. Вы должны показать, что вы пытались, как я уже сказал, совершенно корректно, поэтому это будет скорее проблема с тем, что 'arg' is – Sayse

ответ

5

Из того, что я могу сделать, что Вы можете построить ключ, а затем передать в арг построить Dict, а затем включить, что в фильтре

key = '%s_%s' % (kwargs['m0'], kwargs['m1']) 
result = Artists.objects.filter(**{key: arg}) 
+2

'{key, arg}' или '{key: arg}'? – itzMEonTV

+1

Удивительный! Спасибо, миллион раз! –

+0

@itzmeontv - Спасибо! Ejonas, не беспокойтесь, наслаждайтесь – Sayse

1

Основная и невероятно мощная идея в Python является то, что вам может передать список позиционных аргументов без написания args[0], args[1],... и/или в Словаре аргументов ключевых слов без написания foo=kwargs["foo"], bar=kwargs["bar"],... с помощью * и ** как в func(*args, **kwargs)

функции можно также записать, чтобы принять список позиционных аргументов произвольных длина и любой набор аргументов несогласованного ключевого слова: def func(a, b, c=0, *args, **kwargs). (args и kwargs не зарезервированные слова, только обычные имена переменных)

Этот пример, вероятно, показывает большую часть его в эксплуатацию:

>>> def foo(a, b=0, c=0, *args, **kwargs): 
... print("a,b,c: ", a, b, c) 
... print(args) 
... print(kwargs) 
... 
>>> foo(*[1,2,3,4], **{"baz":42}) 
a,b,c: 1 2 3 
(4,) 
{'baz': 42} 

>>> foo(1, b=2, **{"baz":42, "c":3}) 
a,b,c: 1 2 3 
() 
{'baz': 42} 

>>> foo(**{"baz":42, "c":3, "a":1, "zork":"?" }) 
a,b,c: 1 0 3 
() 
{'zork': '?', 'baz': 42} 

kwargs является ДИКТ, так что если вы хотите, вы можете использовать kwargs.keys() и все другие dict методы для анализа того, что пользователь фактически передал и проверил, проанализировал, обработал и т. д. Django часто использует kwargs.pop(), чтобы разрешить выборку аргументов для текущей функции, оставляя другие именованные аргументы для распространения вниз, возможно, с глубоким набором вложенных функций invocations пока процедура в нижней части не найдет необязательный аргумент ключевого слова свой.

+0

Спасибо! Моя проблема в том, что я не ставил ** перед моей переменной dict. Спасибо за подробный ответ! –