2016-09-29 4 views
3

Я читаю о просмотрах шаблонов через учебник, а некоторые из кода меня путают. Автор использовал этот образец кодаTemplate View - kwargs and ** kwargs

from django.utils.timezone import now 

class AboutUsView(TemplateView): 
    template_name = 'about_us.html' 

def get_context_data(self, **kwargs): 
    context = super(AboutUsView, self).get_context_data(**kwargs) 
    if now().weekday() < 5 and 8 < now().hour < 18: 
     context['open'] = True 
    else: 
     context['open'] = False 
    return context 

что меня смутило синтаксически было это заявление

context = super(AboutUsView, self).get_context_data(**kwargs) 

, если мы уже получаем **kwargs, то почему мы передаем его в супер-функции с ** (двойной Начало). Я думаю, мы должны передать его как

context = super(AboutUsView, self).get_context_data(kwargs) 

это contextMixin, который принимает этот вызов.

class ContextMixin(object): 
    """ 
    A default context mixin that passes the keyword arguments received by 
    get_context_data as the template context. 
    """ 

    def get_context_data(self, **kwargs): 
     if 'view' not in kwargs: 
      kwargs['view'] = self 
     return kwargs 

Из того, что я прочитал, что использование **kwargs в значительной степени означает, что kwargs в настоящее время словарь и должно быть преобразовано в именованное значение. Если это правильно, то каким образом kwargs может быть словарем, когда его параметр фактически равен ** kwargs. Надеюсь, мой вопрос имеет смысл. Пожалуйста, дайте мне знать, если вы хотите, чтобы я перефразировал это.

ответ

3

В объявлении функции **kwargs будет принимать все неопределенные аргументы ключевого слова и преобразовывать их в словарь.

>>> test_dict = {'a':1, 'b':2} 
>>> def test(**kwargs): 
...  print (kwargs) 
... 
>>> test(**test_dict) 
{'b': 2, 'a': 1} 

Обратите внимание, что словарь объект должен быть преобразован с помощью **, когда он передается функции (test(**test_dict)) и, когда оно получено с помощью функции. Это невозможно сделать следующее:

>>> test(test_dict) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: test() takes 0 positional arguments but 1 was given 

Таким образом, в вашем примере, первый **kwargs распаковывает именованные аргументы в словарь, а затем второй упаковывает их обратно для отправки к родителю.

Функция с **kwargs в подписи может получить нераспечатанный словарь или неопределенные аргументы ключевого слова. Вот пример второго случая:

>>> def test(arg1, **kwargs): 
...  print (kwargs) 
... 
>>> test('first', a=1, b=2) 
{'b': 2, 'a': 1} 
+0

ОК, это определенно имеет смысл. Спасибо за очищение этого –

+0

Кстати, как вы знаете, что kwargs в 'def get_context_data (self, ** kwargs):' фактически получает словарь? –

+0

@JamesFranco см. Мое редактирование: большую часть времени это предназначено для получения неопределенных аргументов ключевого слова. – brianpck

2

Здесь в определении функции, она принимает несколько аргументов, и разбор их в Словаре. def get_context_data(self, **kwargs):

Так что теперь kwargs является объектом словаря. Поэтому, если вы передадите его .get_context_data(kwargs), ему придется ожидать только одного входящего аргумента и рассматривать его как словарь.

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

+0

, так вы говорите, что можете преобразовать несколько аргументов в словарь, используя ** также? Я думал, что мы можем преобразовать только словарный словарь в несколько аргументов, используя ** –

+0

Он зарезервирован для функций и lamdas для преобразования аргументов ключевого слова в словарь, так что, к сожалению, нет. Но вы можете упаковать вещи с * как * args в python3. http://peter-hoffmann.com/stackoverflow/36908.html – CasualDemon

Смежные вопросы