Распаковка кортежа 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, или есть какие-либо причины, почему этот случай является недопустимым синтаксисом?

Почему Я уход

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

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

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

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

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

1 54

1 ответ:

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

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

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

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

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