Распаковка кортежа Python в инструкции return

язык Python (особенно 3.x) позволяет очень общий распаковка итераций, простым примером которых является

a, *rest = 1, 2, 3

на протяжении многих лет, эта распаковка постепенно обобщенные (см., например,PEP 3132 и PEP 448), позволяющ ему быть использованным в больше и больше обстоятельствах. Как так, я был удивлен, обнаружив, что следующий недопустимый синтаксис в Python 3.6 (и остается таковым в Python 3.7):

def f():
    rest = [2, 3]
    return 1, *rest  # Invalid

Я могу заставить его работать, инкапсулируя возвращаемый Кортеж в круглые скобки, например:

def f():
    rest = [2, 3]
    return (1, *rest)  # Valid

тот факт, что я использую это в return утверждение кажется важным, как

t = 1, *rest

действительно законно и приводит к тому же с круглыми скобками и без них.

этот случай просто был забыт разработчиками Python, или есть какая-либо причина, по которой этот случай является недопустимым синтаксисом?

Почему Я care

это нарушает важный контракт, который, как я думал, у меня был с языком Python. Рассмотрим следующее (также допустимое) решение:

def f():
    rest = [2, 3]
    t = 1, *rest
    return t

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

def f():
    rest = [2, 3]
    return 1, *rest

это, конечно, не имеет большого значения, чтобы разместить скобки вокруг возвращаемого значения, но обычно дополнительные скобки необходимы только для различения нескольких возможных результатов (группировка). Здесь это не так, поскольку опущение скобок не вызывает какого-либо другого нежелательного поведения, а скорее вообще никакого поведения.

1 ответов


Я подозреваю, что это несчастный случай, исходя из комментариев этот коммит для Python 3.2.

эта фиксация позволила выражению назначения принять testlist_star_expr production (что позволяет распаковывать unparenthesized), но оставил оператор return с testlist производства. Я подозреваю, что фиксация просто пропустила это (и, возможно, другие места, но я фокусируюсь на return_stmt производство на данный момент).

Я пошел вперед и модифицировал Python Grammar / файл грамматики, чтобы позволить это. Все тесты продолжают проходить, в том числе и в test_grammar.py файл (но это не кажется ужасно исчерпывающим).

Если вам интересно, это изменение, которое я сделал. Не стесняйтесь клонировать или скачать вилки.

обновление: я представила проблема bpo и a pull-запрос для возврата (и выхода) распаковки.