Как определение foo(*, a=1) в python соответствует формальному «списку аргументов» в справке по документации?

Недавно я изучал *args и **kwargs в python и обнаружил, что в python 3 можно использовать голый *, как в примере из заголовка, чтобы указать, что после него не разрешены позиционные аргументы.

Проблема в том, что я не понимаю, как это соответствует формальному определению или «списку аргументов» по ссылке. Существует следующее определение списка аргументов:

argument_list        ::=  positional_arguments ["," keyword_arguments]
                        ["," "*" expression] ["," keyword_arguments]
                        ["," "**" expression]
                      | keyword_arguments ["," "*" expression]
                        ["," keyword_arguments] ["," "**" expression]
                      | "*" expression ["," keyword_arguments] ["," "**" expression]
                      | "**" expression

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

Если мы предполагаем, что expression может быть пустым, то следующие определения должны быть действительными:

def foo(*)
def bar(*,**kwargs)

Эти определения не имеют смысла, так как * требует аргументов ключевого слова после него.

Так что буду рад любым разъяснениям по теме. Что мне не хватает? Или приведенный выше БНФ не совсем корректен?


person Phoenix    schedule 10.07.2013    source источник


Ответы (1)


Часть грамматики, на которую вы смотрите, описывает вызовы функций. И голый * действительно недействителен в вызове функции.

грамматика определения функции находится в другой части справочника по языку. Эти постановки актуальны:

parameter_list ::=  (defparameter ",")*
                    ( "*" [parameter] ("," defparameter)* ["," "**" parameter]
                    | "**" parameter
                    | defparameter [","] )
parameter      ::=  identifier [":" expression]
defparameter   ::=  parameter ["=" expression]

Обратите внимание, что здесь parameters и defparameters не обязательны после *.

Ошибка, которая жалуется на def f(*) и def f(*, **kwds), не связана с грамматикой. Это законно с точки зрения грамматики и успешно анализируется. Только во время создания AST это обнаруживается и помечается как ошибка . Это не единственное синтаксическое ограничение, которое не обрабатывается грамматикой.

person Community    schedule 10.07.2013
comment
Спасибо, теперь я вижу, что я пропустил. Но разве это определение не должно принимать мои последние два примера: def foo(*) и def bar(*, **kwargs)? Другими словами, это определение не требует, чтобы за голыми * следовали именованные аргументы. И интерпретатор сообщает об ошибке в случае приведенных выше примеров - person Phoenix; 11.07.2013
comment
@Phoenix Хороший вопрос. Я бы сказал, что это определение должно принимать эти примеры, но, возможно, я ошибаюсь. Я не могу найти ничего запрещающего это и в настоящей официальной грамматике. Может быть, я разучился читать контекстно-свободные грамматики, или это одно из ограничений, накладываемых не парсером, а компилятором. - person ; 11.07.2013
comment
Благодарю вас! Интересно, почему ограничение появилось в генерации AST вместо грамматики. Я предполагаю, что это можно было бы включить в грамматику, явно написав несколько случаев, которые включают * - person Phoenix; 11.07.2013