Создатель Питона: я устал, я ухожу

https://mail.python.org/pipermail/python-committers/2018-July/005664.html
  • Перевод

Теперь, когда PEP 5721 готов, я хочу чтобы это был последний PEP за который мне пришлось так отчаянно сражаться сталкиваясь с таким количеством людей презирающих моё мнение.


1 PEP или Python Enhancement Proposal — предложение по расширению Питона.

PEP 572 останется в истории не только как последний PEP эпохи Гвидо ван Россума, но и благодаря новому оператору присваивания который вызывал неоднозначную эмоциональную реакцию пользователей Питона.

Я бы хотел полностью исключить себя из процесса принятия решений. Я ещё буду доступен какое-то время как обычный старший разработчик2, и я ещё буду продолжать менторить3, у меня даже будет на это больше времени. Но в сущности, я отправляю себя в постоянный отпуск с должности Великодушного пожизненного диктатора4, и отныне вы будете сами по себе.


2 Старший разработчик Питона — Python Core Dev, человек имеющий право комитить без ревью прямо в мастер. Подписывает особое соглашение. Принимается сложным процессом.

Гитхаб показывает 590 контрибьюторов в мастер, из которых 67 комитили и мержили в мастер за последний месяц.

3 Менторить — обучать, подсказывать, помогать начинающим во всём разобраться.

4 Великодушный пожизненный диктатор — термин придуманный случайно в день когда в майл-группе формировалась первая официальная Питон-организация и Гвидо ван Россуму не досталось никакой "нормальной" должности.

Когда-нибудь это всё-равно должно было произойти, в конце концов этот пресловутый автобус5 всегда таится где-то за углом, а я не становлюсь моложе. (Не буду утомлять списком всех своих проблем со здоровьем).


5 Имеется ввиду выражение "bus factor" — фактор автобуса, или фактор риска связанный с тем, что ключевая фигура предприятия или проекта может внезапно погибнуть или утратить дееспособность. Обычно указывает на недостаток распределённости в принятии решений и наличие чрезмерной концентрации власти или ответственности в руках одного человека.

Я не стану назначать себе преемника.


А что же теперь сделаете вы? Создадите демократию? Анархию? Диктатуру? Федерацию?


Я не переживаю за ежедневное принятие решений в баг-трекере6 на Гитхабе. Моё мнение там спрашивают очень редко, и обычно в нём нет особой нужды. Так что с этим, думаю, можно просто работать как обычно.


6 GitHub issues

Вопросы которые сейчас, наверное, важнее всего:


  • Как будут приниматься решения по PEP
  • Как будут приниматься новые люди в старшие разработчики

Может быть у нас получится эти процессы тоже оформить как PEP, может из этого даже получится нечто вроде конституции. Но вот в чём подвох, я оставляю вас всех (текущих комитеров) разбираться с этим самим, без меня.


Учтите, что остаются Правила7, если вам этот документ не нравится, вам остаётся только добровольно покинуть эту группу8. Возможно ещё придётся разобраться как кикать9 людей из этой группы, а также из python-dev и python-ideas, поскольку они тоже подчиняются Правилам.


7 Правила Питон-сообщества (CoC, Python Community Code of Conduct)
8 Имеется ввиду майл рассылка python-committers где это сообщение было опубликовано.
9 Кикать — исключать из любого онлайн сообщества, лишать членства.

И наконец. Напоминаю, что архивы этой группы публичны, хотя членство закрытое (писать могут только старшие разработчики).


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


Гвидо ван Россум (python.org/~guido)
12 июля 2018
Майл-рассылка python-committers


image


Ссылки:
Оригинал сообщения (англ.)
PEP 572 Assignment Expressions
Старший разработчик Питона (англ.)
Википедия: Великодушный пожизненный диктатор
История термина "Великодушный пожизненный диктатор" (англ.)
Правила сообщества (англ.)
Архивы группы комитеров питона (англ.)

Поделиться публикацией
Комментарии 302
    +2
    Грустно, но неизбежно. Непонятно только, почему оставил «разбираться самим», можно же было бы как-то организовать, а то какая-то сознательная организация смуты.
      +28
      Он же не детей со спичками оставил. Это взрослые люди, в самостоятельности которых он достаточно уверен.
        +2
        //So what are you all going to do? Create a democracy? Anarchy? A
        dictatorship? A federation?

        Может только мне так кажется, но вот тут не видится мне уверенности достаточной в тех самых людях, как и в общем тоне сообщения. Даже видится какая-то неуверенность больше.
          0

          Неуверенность в том, что будет дальше. Оно и очевидно, если раньше он играл ключевую роль в принятии решений, сейчас такого человека нет. И появится ли он — неизвестно. И каким либо хаотическим (в хорошем смысле слова) образом мы получим одну из обозначенных выше формаций

            +1
            Всегда находится тот кто возглавит, вы прям как «если не Путин, то кто», инициативных людей много.
              0
              Нет нет. Тут в другом дело. Если люди примерно одинакового уровня инициативности и вежливости, то не обязательно будет новый «Путин» и новая монархия. Многие организации успешно управляются и без такого лидера. Хотя с точки зрения PR и маркетинга, от харизматичного лидера выигрывает любая компания.
            0
            Это больше любопытство, а не неуверенность.
              +2
              А может ему просто хочется, чтобы его попросили остаться. Признали его правоту.
                +2
                Лучше бы вместо нового оператора присваивания сделали настоящие треды. То, что в Go есть нормальные треды, а в Питоне только мультипроцессность, приводит к падению популярности Питона. Я понимаю, что для неопытных разработчиков нужен GIL, так как они не осилят справится с рейсингом, но почему бы не оставить GIL по-умолчанию, не добавив так же что-то вроде true_multithread модуля, а так же его поддержку во все модули стандартной библиотеки?

                Эта фейковая мультитредность, выгодная только когда узкое место диск или сеть, убивает питон :( Особенно в эпоху, когда в процессорах всё больше ядер :(
                  +5
                  Я понимаю, что для неопытных разработчиков нужен GIL, так как они не осилят справится с рейсингом, но почему бы не оставить GIL по-умолчанию, не добавив так же что-то вроде true_multithread модуля, а так же его поддержку во все модули стандартной библиотеки?
                  Потому что это бессмысленно. Сделать такое можно, это даже несколько раз проделывалось (скажем разработчики GLibC упорно тянут эту тему), но оказалось что писать библиотеки, которые эффективно использовать и в однопоточных системах и в многопоточных — ещё сложнее, чем те, которые «знают» и используют многопоточность.

                  Потому лучше уж два языка: один — принципиально многопоточный, другой — принципиально однопоточный.
                    +3

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


                    Если вы интересуетесь авто-мото темой, то наверняка заметили, что львиная доля трепотни об авто — это обсуждения наподобие: «Как жаль, что нет авто, с двигателем, который проезжает 1,000,000 км без капиталки, который отлично управляется на треке, в городе, и проезжает в болоте, да еще, чтобы стоил дешевле $20,000 и налоги на него были невысокие». Или в мото: «Хочу турэндуро с движком 1,5 л и 200 лошадей, чтобы и на треке гонять, и в выходные по лесу. И с запасом хода от 500 км. При этом быть легче 150 кг, легко рулиться, и быть невысоким».


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


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


                    Если бы существовал идеальный инструмент для всех задач, то все бы на него перешли, и language holywars ушли бы в прошлое.

                      0
                      В своём докладе на PyCon Russia 2016 Реймонд Хеттингер рассказывал о выборе технологий, где он оправдывал выбор Питона выделив 3 класса программ (эту классификацию предложил Алекс Мартелли, автор Python Cookbook):

                      • 1-поточные, 1-процессные
                      • многопоточные и многопроцессные
                      • распределённые вычисления


                      Наблюдение Мартелли заключается в том, что первая категория программ может решать всё более сложные задачи в связи с ростом скорости одного ядра CPU. Поэтому вторая категория становится всё менее актуальной (за исключением игр, а я бы добавил сюда VR и всякие мультимедийные приложения типа обработки аудио, монтажа видео и пр.). К тому же основная проблема со второй категорией в том, что она плохо масштабируется — если объём требуемых вычислений возрастает немного, то одного процессора уже не хватает (потому что уже используются все ядра) и задача перетекает в другой класс. Поэтому, по мнению Мартелли, иногда лучше сразу писать для распределённых вычислений (Amazon и пр.).

                      Во-первых рассуждения Мартелли мне кажутся устаревшими (второе издание Python Cookbook, в котором автором был Мартелли, вышло в 2005 году) — сейчас мы видим значительное снижение скорости роста производительности одного ядра, а количество ядер напротив разрослось уже до 20+ — и это не серверные процессоры.

                      Во-вторых эту логику (правильную — следует оценивать экстремумы) можно обратить против Python — он настолько неприлично медленный (я сейчас даже не про GIL и concurrency, а вообще), что его очень быстро начинает не хватать даже для задач 1-й категории. Python плохо масштабируется. Поэтому используя его мы рискуем гораздо больше, чем в случае остальных языков — задача может перетечь в другой класс гораздо раньше.
                        +1

                        Честно говоря, я пока еще не встречался с задачами, где затык в производительности был бы именно в Python, поэтому ничего о производительности интерпретатора не знаю.


                        Но ведь идет же постоянная работа над новыми версиями, и Python используется в больших корпорациях, наверняка, у них есть ресурсы, чтобы оптимизировать интерпретатор до уровня того же Perl. Это вряд ли невыполнимая задача, может быть даже проще решаемая, чем для Perl и JS.


                        Но раз этого не делают, значит никому оно и не надо?

                          +1
                          Тиничная история развития проекта на Python в больших корпорациях выглядит примерно так. Краткое содержание истории для тех, кто не хочет кликать или не знает английского: Гвидо Ван Россум (да, сам лично) написал нам классный Mondrian/Rietvield, к которому мы прикрутили кой-какие фишки., потом ещё… а потом нас задолбало, что оно тормозит и глючит — и мы переписали всё на Java.

                          Разумеется при таком подходе оптимизировать интерпретатор до уровня того же Perl — особо не нужно…
                            +2

                            Я не увидел по ссылке «тормозит и глючит», а увидел: «Ван Россум не захотел добавлять те плюшки, которые нужны нам, вот мы и форкнули».


                            Да и вообще, это какой-то слишком уж упрощенный взгляд.


                            И скорость еще не главное. Вот есть очень быстрый, довольно популярный (для своего времени, во всяком случае) проект на Perl под названием awstats. По бенчмаркам он затыкает по скорости практически всех конкурентов. Но код там такой… Волосы на голове шевелятся и стремятся уйти.

                              +1
                              Я не увидел по ссылке «тормозит и глючит», а увидел: «Ван Россум не захотел добавлять те плюшки, которые нужны нам, вот мы и форкнули».
                              А ничего что после Ван Россума, написавшевго Mondrian/Rietveld были ещё Gitosis/Gitolite и первая версия Gerrit'а? Всё это — на основе всё того же кода?

                              А вот уже переписанная версия — даже отдельного названия не получила, только номер?

                              В том-то и дело, что переписываения произошло внутни развития одного проекта, а не как переход от одного проекта к другому.

                              Странно, что вы там этого не увидели…

                              Но код там такой… Волосы на голове шевелятся и стремятся уйти.
                              Ну вот и с питоном — та же фигня. Просто начиная с какого-то момента код с динамической типизацией становится неподдерживаемым.

                              Это может быть из-за большого количества данных (== «тормозит» из моего описания выше), но у крупных компаний, зачастую — из-за размеров кодобазы (== «глючит» оттуда же).

                              PEP 484 оттуда родился — но пока мало статистики, на которой можно понять — реально решает он проблему или нет…
                                0
                                Просто начиная с какого-то момента код с динамической типизацией становится неподдерживаемым.
                                Это, в первую очередь, зависит от кривизны рук, а не от вида типизации.
                                с какого-то момента
                                С какого момента? После n-лет разработки или после n-Мб кода? Если это происходит когда python код переваливает за 10Мб, то можно не волноваться — для 99,9% проектов этого лимита хватит.
                                  –1
                                  Просто начиная с какого-то момента код с динамической типизацией становится неподдерживаемым.
                                  Это, в первую очередь, зависит от кривизны рук, а не от вида типизации.
                                  Возможно. Но факты — вещь упрямая. Если над проектом работают несколько сотен программистов, то код, на динамическом языке без типизации «рассыпается». Проверно многократно.

                                  С какого момента? После n-лет разработки или после n-Мб кода?
                                  После того, как на проекте разработчики сменятся 2-3 раза. Или просто когда их станет больше 100. Потому что между тем местом, где порождён неправильный тип и где он вызвал выброс исключение оказывается слишком много компонент. А без разбиения продукта на компонетны вы вообще ничего не сотворите в команде в пару тысяч человек.

                                  Если это происходит когда python код переваливает за 10Мб, то можно не волноваться — для 99,9% проектов этого лимита хватит.
                                  В «мелких» компаниях — может быть. Но речь шла о крупных. О том почему они не могут «допилить» python хотя бы до уровня perl'а.

                                  Ответ: потому что им это не нужно по вышеописанным причинам. А у мелких компаний свободных ресурсов нету.
                                    0
                                    После того, как на проекте разработчики сменятся 2-3 раза. Или просто когда их станет больше 100
                                    Ну вон например в джанго почти 900 контрибьюторов, и ничего не развалилось.
                                      –2
                                      А сколько из этих 900 контрибьютеров работают на фуллтайм? Насколько я знаю Django — это небольшой проект, там порядка 100'000 строк кода.

                                      И да, они прикладывают очень много усилий для того, чтобы «не развалилось»: огромное количество документации, тестов и прочего для такого, относительно небольшого, проекта.
                                        0
                                        И да, они прикладывают очень много усилий для того, чтобы «не развалилось»: огромное количество документации, тестов и прочего для такого, относительно небольшого, проекта.


                                        Вы так говорите, как будто это что-то плохое
                                          0
                                          Это нивелирует достоинства Питона. Питон, вообще говоря, более лаконичен, чем C++ или Java. И, соотвественно, написать что-то на нём можно быстрее.

                                          Но если выясняется, что для того, чтобы всё это работало, вам требуется потратить ещё вдвое-втрое больше времени на написание документации и тестов, то это преимущесво нивелируется, а недостатки (на два порядка меньшая скорость работы, невозможность использования многоядерных процессоров) — остаются.
                                            +2
                                            Но если выясняется, что для того, чтобы всё это работало, вам требуется потратить ещё вдвое-втрое больше времени на написание документации и тестов
                                            Для проектов со статической типизацией тесты и документация важны не меньше, тут вы не выиграете, кроме того оно не влиет на то работает приложение или нет.

                                            У вас ложные домыслы, вы хаете чужое «болото» не видя картины в целом, пообщайтесь с профисиаоналами которые разратывают одновременно на питоне и с++ (java).

                                            невозможность использования многоядерных процессоров
                                            Опять домыслы, в питоне нет проблем загрузить все ядра процессора.

                                            на два порядка меньшая скорость работы
                                            У меня был реальный случай где было написано 2 варианта одного компонента на python и golang, дак вот python вариант был в 3 раза быстрее за счет того что там использовалась маленькая с++ вставка. Вы можете сказать «дак это из-за с++», дак вот так и надо разрабывать, кроме того много библиотек под питон как раз написаны на с/с++.

                                            PS: На счет «меньшего» кол-ва ошибок со статической типизацией есть смешной случай от Гвидо.
                                              0
                                              Для проектов со статической типизацией тесты и документация важны не меньше
                                              Вам не нужно ни описывать, ни тестировать параметры большинства функций в статически типизированном языке. Само описание является и документацией и тестом, причём, что важно — обойти их, без специальных ухищрений нельзя.

                                              А насчёт «профессионалов, пишущих на python и на других языках» — ну я, например, сам таким являюсь. С этого всё и началось: с наблюдения, что большие проекты, изначально написанные на python'е, рано или поздно оказываются переписанные на Java (чаще), либо C++ (реже).

                                              Когда этот вопрос подняли, то в ходе дискуссии был упомянут как раз Геррит — типа «если проект написан самим Гвидо, то он, возможно, сможет жить и на питоне»… после чего кто-то прислал ссылку на как раз разрабатываемую вторую версию — после чего вопрос был закрыт.

                                              Мелкие утилиты, кстати, и у нас часто на python пишут до сих пор.
                                                0
                                                Вам не нужно ни описывать, ни тестировать параметры большинства функций
                                                Как и в питоне (зависит от проекта, исключение — публичные библиотеки, хотя для них делают доку и для «статических тип. языков» тоже), пример — исходники djangocms, параметры почти нигде не описаны, входные параметры так же почти нигде не проверяются — и это не проблема.

                                                А насчёт «профессионалов, пишущих на python и на других языках» — ну я, например, сам таким являюсь.
                                                Ок, видимо сделал неверный вывод по тому как у вас какие-то сложности использовать питон на всех ядрах процессора.

                                                большие проекты, изначально написанные на python'е, рано или поздно оказываются переписанные на Java (чаще), либо C++ (реже).
                                                Это вовсе не означает, что старт на питоне был ошибкой. Тут часто упоминают теорию — что если бы они изначально начали с java/c++ то стартап не взлетел бы вообще. А мотивация переписывания может быть вызвана другими причинами.

                                                Кстати, я сейчас подумал — что развивать проект с исходниками в 10Мб по сложности должно быть сопоставимо с проектом в 100Мб+, т.к. архитектура уже выстроена и проект просто прирастает новыми компонентами/микросервисами. С такими объемами одному человеку не возможно знать весь прокт досконально. А если так, то у питона нет особых проблем с большими проктами при правильной архитектуре.
                            0
                            Оптимизировать до уровня perl? Язык perl переживает не лучшие времена, и вы того же желаете python?
                              0
                              Вообще-то есть PyPy
                                +1
                                Я с такими задачами встречаюсь регулярно. Достаточно часто приходится, скажем, распарсить лог, собрать статистику или построить график, и то, что пишут на питоне, работает на порядок медленнее, не параллелится и зачастую ест больше памяти.
                            +1
                            Лучше бы вместо нового оператора присваивания сделали настоящие треды.

                            Пробовали уже, например здесь или здесь. Почему эти реализации широко известны только в узких кругах, это другой вопрос.
                            GIL, скорее всего, был добавлен для упрощения реализации, в то время, когда поддержка потоков была не особо актуальна, например, потому, что был perl, который справлялся и в один поток. Правда это мое мнение, с которым вы можете не согласится. :)


                            приводит к падению популярности Питона

                            Не согласен. Пых, которому предсказывают закат последние лет 10, и питон — одни из самых востребованных языков. Я как раз ищу работу, и отслеживаю вакансии.

                              +1
                              Да, странное утверждение про падение популярности Питона. По всем рейтингам Питон входит в самый топ, топ-5, в худшем случае в топ-10. И ещё и растёт. Питон делают учебным языком в ВУЗах.
                                0
                                Мне кажется, автор коммента имел ввиду, что это не позволяет использовать питон для более широкого круга задач. В итоге "- А почему вы не взяли питон? — Так там нормальных тредов даже нету!", что совсем не продвигает язык.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    0
                                    Питон медленный язык. В общем случае он медленнее того же перла, про гоу и говорить нечего. Библиотеки к питону, требующие скорости, скорее всего окажутся написанными на си, а от питона там только биндинг. И при установке из исходников нередко начинаются проблемы с компиляцией сишной части.
                                    Одна программка, опрашивающая сетевое оборудование, на питоне цикл опроса занимал полторы минуты, на гоу без изменения алгоритма стало 4 секунды. Как-то так.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                        0
                                        Потому что язык интерпретируемый :)
                                        Есть более скоростные реализации, чем CPython,
                                        но они не так распространены.
                                          0
                                          Как вы собрались к языку, в котором есть eval компилятор прикручивать?

                                          Как и для любого подобного языка есть компиляторы с подмножества+надмножества (Cython, к примеру), но это уже не совсем Python.
                                            +1
                                            Как вы собрались к языку, в котором есть eval компилятор прикручивать?

                                            Это редко используемая команда. А в случаях, когда она всё же используется, вполне можно из скопилированной программы дёргать libpython.


                                            Да, eval — это команда, интерпретирующая строку на Python. Но это не значит, что программа, которая её содержит, не может быть скомпилирована.


                                            Можно сказать, например, что библиотека V8 добавляет в C++ команду eval, выполняющую код на js. Это же не делает компиляцию C++ невозможной.


                                            Скажем, компилятор Nuitka, который я упомянул ниже, полностью совместим с Python 3.6.

                                            0

                                            Есть компиляторы. Например, Nuitka.

                                            +2
                                            Одна программка, опрашивающая сетевое оборудование, на питоне цикл опроса занимал полторы минуты, на гоу без изменения алгоритма стало 4 секунды. Как-то так.
                                            Возможно, если кол-во сетевых оборудований исчисляется сотнями тысяч, но скорее всего программа просто криво написана либо помимо io программа делает кучу вычислений. Питон может обрабатывать до 100krps (и более) в один поток — для опроса оборудования этого достаточно.
                                              0
                                              SSH не обработает 100krps в силу медленности самого SSH.
                                              А SNMP, ну, не знаю, как-то так:

                                              from pysnmp.entity.rfc3413.oneliner import cmdgen
                                              cmdGen = cmdgen.CommandGenerator()
                                              errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
                                              cmdgen.CommunityData(community),
                                              cmdgen.UdpTransportTarget((host, 161)),
                                              oid_in_octets)

                                              даже после перехода с перла на питон удивило, что SNMP стало работать заметно медленнее, не критично, но всё равно.
                                                0
                                                Вы, что-ли, последовательно опрашиваете оборудование?
                                                ssh/snmp можно использовать под asyncio — отправляете команду сразу на 1000 девайсов, через пару* секунд у вас результат с 1000 девайсов.
                                                Если девайсов не так много то можно завернуть готовый синхронный код в потоки (они в питоне настоящие, хотя и с нюансами).

                                                силу медленности самого SSH
                                                В том и дело, что это по большей части зависит от сервера и сети, без разницы на чем клиент написан.
                                                  0
                                                  Я в потоки и заворачивал. Последовательно опрашивать это ни в какой приемлемый интервал не поместится.
                                                  Вот c asyncio не пришлось иметь дело.
                                                  0

                                                  pysnmp — библиотека не из stdlib. Вполне возможно, что она просто неэффективно написана.

                                                  0
                                                  Расхожая под питоном библиотека netmiko ужасно медленная штука.
                                                +2
                                                Если то, что про скорость Питона написал один из комментаторов правда, то не важно есть там треды или нет — в этом случае ограничителем является скорость, а не наличие/отсутствие тредов.


                                                Скорость синглтреда у CPU почти не растёт, тогда как количество ядер растёт. Есть граница, когда более медленный питон приемлим, и когда уже нет. То, что он не поддерживает легковесные треды, а только процессы (со своими ограничениями...), год за годом увеличивает такой разрыв.
                                                Я бы очень хотела появления в питоне хоть и более медленных тредов, чем в Go, но всё же настоящих, а не таких, как сейчас, которые работают только медленнее на любом CPU-интенсив коде. Хочется, чтобы масштабирование было не линейным только из-за закона Амдала, а не по тому, что GIL
                                                  +2
                                                  Вообще, для численных вычислений эта проблема во многом уже решена, например распараллеливание достигается всего одной директивой:
                                                  @numba.jit(nopython=True, parallel=True)
                                                  def logistic_regression(Y, X, w, iterations):
                                                      for i in range(iterations):
                                                          w -= np.dot(((1.0 / (1.0 + np.exp(-Y * np.dot(X, w))) - 1.0) * Y), X)
                                                      return w
                                                  


                                                  (см. numba.pydata.org/numba-doc/0.39.0/user/parallel.html)
                                                0
                                                А что именно вы имете ввиду под нормальными тредами? Рискну предположить, что речь про Go, но там речь идет про легкие потоки, при которых M горутин отображается на N нормальных потоков ядра. Если так, то честная многопоточность — это достаточно своеобразная задача. Она, к стати, достаточно корошо проработана в контексте асинхронного исполнения кода, и питон максимально близок к, например, Go, в том, что относится к оптимизации исполнения «паралельного» кода, хотя и уступает ему.
                                                Поменять реализацию подсистемы исполнения, чтобы однопоточная реализация питона не потеряла в скорости, при этом появилась возможности исполнять многопточный код — сама по себе задача нетрвиальная. Кроме этого, сто процентов, придется подвергнуть ревизии весь существующий код на питон, потому что старая реализация не подразумевает многопоточность, со всеми вытекающими из этого факта последствиями.
                                                Скорее всего, это и служит препятствием для распространения альтернативных реализаций питон, где с паралельностью ситуация обстоит лучше.
                                                ЗЫ. Я практикую питон начиная года с 2005, и потребность в потоках у меня возникала, от силы, пару раз. Я думаю что прблема отсутствия полноценного массштабирования по ядрам процессора, или по процессорам в случае многопроцессорной системы, имеет место быть, но ее роль сильно преувеличена.
                                                  +2
                                                  и питон максимально близок к, например, Go, в том, что относится к оптимизации исполнения «паралельного» кода, хотя и уступает ему.


                                                  Разве что только в случае I/O и network интенсив кода :(

                                                  я практикую питон начиная года с 2005, и потребность в потоках у меня возникала, от силы, пару раз.


                                                  Я девопс, часто рисую демоны (т.к. поддерживаю инфраструктуру), парсилки терабайтных асинхронных потоков, разные брокеры, и мне нужно постоянно :(
                                  0
                                  Видимо его еще и просто крепко достали.
                                  +20
                                  holywar_started := True

                                  ИМХО PEP 572 совсем не python-style.
                                    +6
                                    (holywar_started := True)

                                    А есть где-то определение python-style?
                                      +2
                                      А чем конкретно по вашему не соотвествует? Короткая, лаконичная форма, используемая во многих языках.
                                        +5
                                        За что многие и любят Питон, так как раз за то что не разрешены конструкции типа таких:
                                            printf("%d",(a++)+(a--)+(++a)+(--a));

                                        Коротко и лаконично, да.

                                        А по поводу нового оператора — я что-то не понял из PEP, как будет решаться такой случай:
                                        if True or (something := a + 456):
                                            print(something)
                                        

                                        Что будет в результате?
                                      +4
                                      Честно говоря, я так и не понял, какую задачу решает этот синтаксис. Судя по коду в PEP, он позволяет сохранить значение выражения, используемого, например, в условии, в переменную.
                                      Т.е. такой код:
                                      diff = a - b
                                      if diff:
                                          doSomething(diff)
                                      

                                      мы можем заменить таким:
                                      if (diff := a - b):
                                          doSomething(diff)
                                      

                                      Не могу сказать, что я хотя бы раз сталкивался с ситуацией, в которой жалел о том, что такой фичи нет в Питоне.
                                        +2
                                        Эммм, а сразу нельзя было сделать (благо в C уже давно был известен с такой фигней) и почему не подходит синтаксис без двоеточия? x = (y = z)
                                          +1
                                          Ну, всегда считалось, что это просто не нужно, например, вот вопрос от 2011 года: https://stackoverflow.com/questions/4869770/why-does-python-assignment-not-return-a-value.
                                          Именно поэтому данный PEP вызвал такую эмоциональную реакцию у сообщества, все считали что это не баг, а фича.
                                            +3

                                            Вообще, насчёт «сразу сделать» в ЧаВо Python’а есть ответ:


                                            Почему я не могу использовать присваивание в выражении?
                                            Почему я не могу использовать присваивание в выражении?
                                            Многие люди, привыкшие к C или Perl, жалуются, что хотят использовать эту идиому C:
                                            while (line = readline(f)) {
                                                // что-то делаем с line
                                            }


                                            в то время, как в Python’е вы вынуждены писать так:
                                            while True:
                                                line = f.readline()
                                                if not line:
                                                    break
                                                ...  # что-то делаем с line


                                            Причина, по которой в выражениях Python’а не допускаются присваивания — распространённая трудноуловимая ошибка в других языках, вызванная следующей конструкцией:
                                            if (x = 0) {
                                                // обработка ошибки
                                            }
                                            else {
                                                // код, работающий только при ненулевом x
                                            }


                                            Ошибка заключается в простой опечатке: x = 0, в результате чего переменной x присваивается значение 0, хотя, конечно же, подразумевалось сравнение x == 0.

                                            Было предложено много альтернатив. Большинство из них было хаками, которые давали некоторую экономию в наборе кода, но использовали странный или непонятный синтаксис или ключевые слова и не отвечали простейшему критерию для предложений об изменении языка: оно должно предлагать человеку, ещё не знакомому с конструкцией, интуитивно правильный смысл.

                                            Интересным наблюдением является то, что большинство опытных программистов на Python’е признают идиому while True и, похоже, не сильно огорчаются отсутствию присваивания в выражениях; сильное желание добавить его к языку выражают только новички.

                                            Существует альтернативный способ написания такого цикла, который кажется привлекательным, но он, как правило, менее надёжен, чем решение с while True:
                                            line = f.readline()
                                            while line:
                                                ...  # что-то делаем с line
                                                line = f.readline()


                                            Проблема заключается в том, что если вы задумаете изменить способ получения следующей строки (например, захотите изменить его на sys.stdin.readline()), вы должны будете помнить о том, что в вашей программе необходимо изменить два места — второе вхождение спрятано внизу цикла.

                                            Наилучший подходом будет использование итераторов, позволяющих перебирать объекты инструкцией for. К примеру, файловые объекты поддерживают протокол итератора, поэтому вы можете просто написать:
                                            for line in f:
                                                ...  # что-то делаем с line...

                                              –2
                                              Это легко решается такой писаниной:
                                              if (0 == x) {
                                              //
                                              }

                                              При забытом втором символе равенства, будет ошибка.
                                                +1
                                                А если сравнивать две переменных?
                                                  0
                                                  Тогда это не работает :)
                                              +3
                                              > Эммм, а сразу нельзя было сделать

                                              В этом вся и проблема — Python 20 лет существовал без этого и тут внезапно, в году 2018 от рождества христова, эта фича резко понадобилась. Кому? Какому-то секретному клану, который 20 лет тихо ненавидел язык за отсутствие этой фичи, но упорно использовал язык дальше, вместо того, чтобы переключиться на один из стопитцати других языков?
                                                +1
                                                Так все популярные языки развиваются. В последних релизах java, js, c++ тоже добавили много фич, но что без них нельзя было?)
                                                  +6
                                                  > В последних релизах

                                                  Эту фичу можно было добавить в язык 20, 15, 10 лет назад. Очень легко, Python сам написан на C, где присваивание является operator, а не statement, так что не подумать о такой возможно было невозможно. Подумали, и *специально* не добавили. Это было отражено в FAQ'ах и так далее. Внезапно добавлять ее через 20 лет эволюции языка — мягко говоря странно. Вообще, ситуация в Python в последних релизах можно отразить одной фразой — «The king is mad». От этого устали и окружающие и, как оказалось, сам король тоже.

                                                  > Так все популярные языки развиваются.

                                                  Это типичная ошибка считать любые изменения «развитием». Часть изменений является «упадком», «гонкой за собственным (или, что хуже, чужим) хвостом» и «метастазами».

                                                  Вот например, только сегодня попалась ссылка по C++: gist.github.com/bkaradzic/2e39896bc7d8c34e042b
                                              +9
                                              Там в начале раздела Syntax and Semantics приведены полезные примеры:
                                              # Handle a matched regex
                                              if (match := pattern.search(data)) is not None:
                                                  # Do something with match
                                              
                                              # A loop that can't be trivially rewritten using 2-arg iter()
                                              while chunk := file.read(8192):
                                                 process(chunk)
                                              
                                              # Reuse a value that's expensive to compute
                                              [y := f(x), y**2, y**3]
                                              
                                              # Share a subexpression between a comprehension filter clause and its output
                                              filtered_data = [y for x in data if (y := f(x)) is not None]


                                              С одной стороны, оно конечно удобно. С другой стороны, с моей дилетантской точки зрения кажется странным сначала избежать возможности ошибок, наподобие «if (x = y)» вместо «if (x == y)», а потом вернуть её.
                                                +17
                                                ":=" и "==" спутать всё-таки трудней, чем "=" и "==". Говорю как человек, многократно проделавший второе.
                                                  0

                                                  Я в руби на этом обжигаюсь время от времени (после многих лет паскаля).

                                                    +1

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

                                                    –6
                                                    Вы серьезно что-ли?
                                                      –4
                                                      Легко, если есть дельфевый проект в конторе.

                                                      Я программировал «одновременно» на Delphi, PL/SQL, Perl, C++, Python и JS (такой зоопарк развёлся, в том числе и моим усилиями, в одной конторе)… так вот в этом зоопарке, я часто втыкал специфичные операторы куда нужно и куда нельзя в других языках.

                                                      Правда я использовал хитрый хак от кого-то из крутых (кажется от Стивенсона), писал в операторах сравнения константу первым операндом. Но честно говоря, после отпуска самому приходилось привыкать к такой нотации.

                                                      if (500 == error_code) {

                                                      Как оно сейчас глаза режет тем кто поддерживает мой код,… хе-хе…
                                                      +4
                                                      В языках где это можно, использование присваивания сразу в сравнении считается плохим тоном. Особенно доставляют вот такие конструкции.

                                                      if (isSomenting = something1 === something2) {

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

                                                      А ведь можно ещё так
                                                      filtered_data = [ z.group(1) if z := re.match(y) else None for x in data if (y := f(x)) is not None]

                                                      А можно ещё и не так. И можно вспоминать старые холивары Python vs Perl, умершие казалось бы с перлом. Поскольку теперь Perl будет казаться отлично структурированным и прекрасно читаемым языком)

                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                          0
                                                          Ну как же, если кто-то в интернете решил не писать на Perl, значит Perl умер :)
                                                            +4
                                                            Ну не то что бы умер. Занял довольно узкие ниши.

                                                            И проблема поиска сильных перлистов была ещё 10 лет назад — не потому что рынок выметен, а потому что спецов стало меньше.

                                                            Как ни странно 5 лет назад мне предлагали работу на перл, но с зарплатой перловому сеньору, процентов на 40 ниже фронтового миддла) Типа поддержка — это не разработка, так зачем платить много )
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                +1
                                                                Просто притока молодежи в перл нет. Приток в дельфи какой-то есть, поскольку в некоторых институтах его возможно «учат» (или уже нет?).

                                                                А вот перл… Хотя в плане обучения перл очень хорош как язык третьего-четвёртого курса. Когда надо учить не просто программировать, а программировать читаемо.

                                                                Надо на эту тему статью тиснуть, похоливарить, жаль первое апреля ещё не скоро))))
                                                                  0
                                                                  С дельфи, или как оно там сейчас называется, не очень просто. Это в девяностых и начале нулевых хорошо было, с пиратством особо не боролись. Покупали диск с дельфи на базаре и вперёд. А сейчас с пиратством софта не очень. У нас были некоторые решения, написанные на дельфи. Потом встал вопрос удаления любого нелицензионного софта. Руководство посмотрело на цену рад студио что-то в районе полумиллиона и сказало, что денег не будет. Вопрос закрыт. Что возможно было переписано на питоне. На фри паскаль/лазарус сконвертировать не удалось.

                                                                  А на перле достаточно просто программировать читаемо. Вопрос, что если сравнить языковые конструкции перла и питона, совершающие одинаковую работу, то на перле выходит не так уж чтобы интуитивно понятно, нужно знать синтаксис. А питон скорее всего поймёт тот, кто питон первый раз видит. Потому люди в питон идут. Те кто не профессионалы, не гуру, а им просто надо решать какие-то задачи небольшого объёма своими силами. Тем более под питон написаны очень крутые библиотеки. И на многие вопросы можно за пару минут найти ответ на стековерфлоу.

                                                                    +2
                                                                    На фри паскаль/лазарус сконвертировать не удалось.
                                                                    Не расскажете в двух словах, почему не удалось? Я как-то сталкивался с парой проектов на лазарусе, весьма приятные впечатления остались. А уж скорость компиляции паскаля, особенно после C++, просто сносит башню, конечно (в девяностые это было не так заметно).
                                                                      0
                                                                      Задачи на дельфи не мои. Когда услышал разговоры про лицензии, деньги, спросил про лазарус. Дельфист ответил, что не получается перенести.
                                                                      А по скорости компиляции сейчас Golang очень хорош. Вплоть до того, что можно через go run просто запускать как в скриптовом режиме.
                                                                        +4
                                                                        Не расскажете в двух словах, почему не удалось?
                                                                        Потому что Delphi — это не только Delphi. Во все проектах, которые видел, половина всего — это куча компонент с непонятными лицензиями и непонятно откуда взявшимися. Под Lazarus всё это придётся переписывать. А если половину придётся переписывать всё равно — то лучше взять более mailstream продукт и переписать всё.
                                                                          0
                                                                          По большому счёту про любой язык можно то же самое сказать. Про тот же питон. Зачем изобретать велосипед.
                                                                          С дельфи немного другая ситуация была во времена расцвета. Не было репозитариев, не было гитхаба. Поэтому действительно можно сказать — непонятно откуда взявшиеся компоненты. Хотя были сайты с большими подборками, но это было народное творчество.
                                                                            +3
                                                                            Про тот же питон.
                                                                            Нет. Про python и perl какой-нибудь так сказать нельзя. Ибо там очень мало комменрческих компонент всегда было.

                                                                            И даже в каком-нибудь C++ не было принято тащить библиотеки неясного происходжения к себе в проект.

                                                                            Не было репозитариев, не было гитхаба.
                                                                            Но был CTAN и был CPAN.

                                                                            Погубило Delphi другое. То, что модули можно было распространять в виде бинарников. С PHP, Perl'ом, Python'ом такое не прокатывало в силу интерпретируемости. С С/C++ — потому что была куча компиляторов и у них были несовместимые бинарники. Плюс, опять-таки, GNU/Linux — туда без чёткой лицензии биболиотеки не допускались, спасиба Столлману.

                                                                            А вот Delphi и Visual Basic — таки да. Причём поскольку Visual Basic был распространён на Западе, где компоненты всё-таки многие покупали, то понять — откуда что взялось всё-таки удавалось.

                                                                            Хотя были сайты с большими подборками, но это было народное творчество.
                                                                            Проблема в том, что всё это «народное творчество» интересовалось соблюдейнием авторского права чуть менее, чем «никак». Соотвественно оно только усугубляло проблему: если нужно было что-то такое «навороитить», то оно помогало, конечно, но если потом, вдруг, возникала задача всё легализовать… Было проще всё выкинуть и заново написать, чем концы найти и связаться с разработчиками компонентов!
                                                                              0
                                                                              Погубило Delphi другое. То, что модули можно было распространять в виде бинарников. [...] Проблема в том, что всё это «народное творчество» интересовалось соблюдейнием авторского права чуть менее, чем «никак». Было проще всё выкинуть и заново написать, чем концы найти и связаться с разработчиками компонентов!
                                                                              Интересное замечание. Получается, то, за что (среди прочего) хвалят паскаль (полноценные модули, честная раздельная компиляция, стабильный ABI, вот это всё) его и погубило?
                                                                                0
                                                                                В одной из версий Делфи была утеряна совместимость со старыми компонентами = то есть убили всё легаси разом.
                                                                                  0
                                                                                  Получается, то, за что (среди прочего) хвалят паскаль (полноценные модули, честная раздельная компиляция, стабильный ABI, вот это всё) его и погубило?
                                                                                  Во многом — да. Наши недостатки — продолжение наших достоинств.

                                                                                  Хотите другой продукт, который постигла та же участь? Windows.

                                                                                  Она прочно оккупировала десктоп, так как под неё есть куча всего, буквально миллионы программ (если учесть всякие внутрифирменные поделки). Но… это всё бинарники. Под десктоп. Потому никакие попытки вырваться с этого плацдарма ну хоть куда-нибудь (многочисленные версии Windows NT под разные RISC процессоры, мобильники и прочее) — к успеху не привели.
                                                                                  0
                                                                                  Погубило Delphi другое. То, что модули можно было распространять в виде бинарников.

                                                                                  Хм, нет. Это как раз фича. Нет форсированного оперсорса, хочешь — публикуй исходники, не хочешь — нет. Тем более, что проприетарные коммерческие компоненты обычно с исходниками поставляются.
                                                                                  Та же система компиляции бинарников (более удобная, чем в delphi) есть в Java. И Java это не погубило. (C#, насколько я понимаю, аналогично)


                                                                                  Если рассуждать о том, что погубило delphi — имхо, это
                                                                                  1) бардак в синтаксисе, одних массивов несколько типов, и между собой они не очень совместимы; классы и интерфейсы (используются для ARC) — это раздельные, не всегда совместимые между собой сущности; и т.д., и т.п.
                                                                                  2) язык отстаёт от прочих. generic'и завезли поздно и криво, синтаксис для лямбд ужасно многословен.
                                                                                  3) ГЛЮЧНАЯ IDE, начиная после delphi 7, а по воспоминаниям олдфагов — с delphi 7. d2007, если не ошибаюсь, могла упасть 5-6 раз за 40 минут на сложных проектах. Что до последней версии IDE, она не может корректно подсвечивать ошибки и форматировать более-менее сложный код с лямбдами. Хотя разработчик IDE и языка — одна контора.
                                                                                  4) убогая стандартная библиотека даже в последних версиях, забагованная нестандартная (jcl).
                                                                                  5) и это всё платно, за довольно большие деньги (в несколько раз дороже, чем visual studio). Нелицензионное использование детектируют и пишут письма счастья.
                                                                                  6) таки есть проблемки при переходе между версиями, но где их нет?

                                                                                    0
                                                                                    таки есть проблемки при переходе между версиями, но где их нет?

                                                                                    С первой на вторую, со второй на третью, с третьей на четвёртую, с четвёртой на пятую — вообще проблем не было.
                                                                                      0
                                                                                      Хм, нет. Это как раз фича. Нет форсированного оперсорса, хочешь — публикуй исходники, не хочешь — нет.
                                                                                      И в ситуации, когда весь софт покупался на лотках в переходе за три копейки большинство разработчиков исходниками не заморачивалось.

                                                                                      Та же система компиляции бинарников (более удобная, чем в delphi) есть в Java. И Java это не погубило. (C#, насколько я понимаю, аналогично)
                                                                                      Пока не погубило. У них пока не было необходимости «сломать» совместимость при переходе на новую платформу. Потому что то, что было сделано изначально — покрывало все современные платформы и поддержка всяких MIPS'ов/Sparc'ов шла из кородки (а ничего нового как и нету).

                                                                                      Если вдруг Java или C# попадут в ситуацию, когда им придётся сломать совместимость — будет то же самое, что и с Delphi (или Windows, как я описывал выше).
                                                                                        0
                                                                                        Ну в Java это был один из главных принципов, что новые версии не должны ломать обратную совместимость. И держались очень хорошо, плоть до 9-ки (хотя сам не проверял, говорю со слов других), говорят, с Jigsaw не все гладко
                                                                                          +1
                                                                                          А в Java разве есть совместимость? Сам стараюсь держаться подальше, но так или иначе оно всегда рядом в крупной компании. Приходится держать пачку разных версий джавы, вплоть до очень старых. И так было всегда. То же самое с платформой .NET. В панели управления в программах и компонентах огромный список разных версий.
                                                                                            0
                                                                                            Там не может быть списка разных версий. Возможно, вы спутали список версий со списком обновлений для них.

                                                                                            Принципиально разных версий .NET Framework всего четыре: 1.0, 1.1, 2.0 и 4.0, причем первые две давно мертвы. Все остальные версии — обновления для какой-то из этих.
                                                                                              0
                                                                                              А в Java разве есть совместимость?

                                                                                              Как правило, библиотека, скомпилированная под что-то древнее, нормально запускается (запускалась) на новых версиях без перекомпиляции. С приходом java9 некоторые (использующие грязные хаки jvm) библиотеки отваливаются.

                                                                                                +1

                                                                                                Мне всегда казалось, что Spring, который использует почти каждый, под капотом использует просто тонну грязных хаков

                                                                                                0
                                                                                                Выше уже сказали. Если вы не пользуетесь XP, то версия дотнета у вас всего одна — 4.х.
                                                                                              +3
                                                                                              Погубил Дельфи развал Борланда начавшийся с неудачной покупки dBASE и привёдший к куче неразрешимых внутрених конфликтов: dBASE против Paradox, C против Pascal и тд. В результате чего поругались и ушли все кто способен был делать софт на мировом уровне: Йенсен, Кан, Хайлсберг, Джервис и наконец Торп.

                                                                                              Скорее всего дело в том, что Борланд изначально европейская (преимуществено Датская) компания с филиалом в США, ну и ушлые янки в результате совестливых интеллигентов отправили домой, а кассу оставили себе. Какого развития средств разработки можно ожидать в итоге?

                                                                                              Не все эту историю знают, но обычные разработчики и менеджеры ещё тогда, в 95 году, почувствовали, что дел иметь больше не с кем, перемены в стратегии и даже в названии, как в погоде, семь пятниц на неделе, нет больше серьёзной компании на которую можно делать ставку. А жаль, это до какой-то поры был редкий пример настоящего успешного европейского менталитета в нашей индустрии. Ван Россум, кстати, другой такой пример.

                                                                              0
                                                                              Не далее как вчера переживал из-за того, что событийная модель в Mojolicious как-то резко уступила место тотальному async/await'у и промисам, и все мои коллеги уже переписали свой Mojo-код на промисы, а я ещё нет. Как вдруг выясняется, что сегодня Perl уже умер (на 5.28'й версии скоропостижно скончался от несбывшихся надежд, R.I.P?). Пойду что ли на PHP всё перепишу, раз такое дело: хабр же не может ошибаться.
                                                                                0
                                                                                событийная модель в Mojolicious как-то резко уступила место тотальному async/await'у и промисам

                                                                                А поддержка событий, надеюсь, не отвалилась?
                                                                              +1
                                                                              Мне очень нравится с этим, эм, сайдэффектом ленивые инициализации в шарпе делать.

                                                                              object _value;
                                                                              public object Value => _value ?? (_value = whatever);

                                                                              (да, я знаю про Lazy, и нет, его нельзя или неудобно использовать в большинстве случаев)
                                                                                +2

                                                                                Есть еще LazyInitializer

                                                                                  0

                                                                                  Капец! Шикарная штука, спасибо, не думал из статьи по Питону найти отличную фишку для C# :)

                                                                              +4
                                                                              А что с with теперь? Можно будет писать и так, и этак?

                                                                              with file := open('filename'):
                                                                                  chunk = file.read('8192')
                                                                              
                                                                              with open('filename') as file:
                                                                                  chunk = file.read('8192')
                                                                              

                                                                              Кстати, как по мне, в циклах и условиях «as» выглядел бы более питонично, а в list comprehensions оба варианта здорово сбивают с толку.

                                                                              if pattern.search(data) as match is not None:
                                                                              
                                                                              while file.read(8192) as chunk
                                                                                 process(chunk)
                                                                              
                                                                              [f(x) as y, y**2, y**3]
                                                                              
                                                                              filtered_data = [y for x in data if f(x) as y is not None]
                                                                              

                                                                              P.S. PEP не читал. Надеюсь, у них были весомые аргументы против того, чтоб расширить область применения «as».
                                                                                +3

                                                                                with ENTERABLE as FOO: присвает Foo не ENTERABLE а результат выполнения ENTERABLE.enter(). В pep про это есть.

                                                                                  0

                                                                                  Маркап попортил сообщение. enter был с подчёркиваниями

                                                                                    –1
                                                                                    Прочитал как ETERNALBLUE… похоже пора завязывать с пентестингом.
                                                                                    –1
                                                                                    Офигенно придумал. Это и python-style, и более очевидно. Два оператора присваивания — это провал.
                                                                                    0
                                                                                    О, то есть теперь можно второму аргументу функции сразу передавать значение первого?
                                                                                    Вроде
                                                                                    def func(a=(x:=0), b=x):
                                                                                        return a+b
                                                                                      +1
                                                                                      Мне почему-то кажется, что в такой конструкции x будет нулем, а не значением первого аргумента!
                                                                                        +1
                                                                                        И в самом деле. Ну, может
                                                                                        def func(x:=a, b=x):
                                                                                            return a+b

                                                                                        сработает
                                                                                        +3
                                                                                        А как быть с тем, что порядок присвоения значений аргументам не определен? Да и значения аргументов по умолчанию должны быть известны во время определения функции, а значения переменных станут известны только во время выполнения. Такая конструкция просто нелегальна, imho.
                                                                                          +4
                                                                                          А как быть с тем, что порядок присвоения значений аргументам не определен?

                                                                                          Undefined behavior — это как раз то, чего нам так не хватало в питоне! Вообще, что это за язык такой без UB? Без UB — это не язык, это так, баловство.

                                                                                      0

                                                                                      Очень долго возможность присваивания в цикле или проверки считалась багом и источником ошибок.


                                                                                      if (diff := a - b):
                                                                                          doSomething(diff)

                                                                                      и


                                                                                      if (diff == a - b):
                                                                                          doSomething(diff)
                                                                                        +5
                                                                                        Там самый кайф не в таких простых конструкция, а в чуть более сложных, в которых эта техника позволяет избежать от глубоких if'ов:

                                                                                        Без глубоко и громоздко:
                                                                                        reductor = dispatch_table.get(cls)
                                                                                        if reductor:
                                                                                            rv = reductor(x)
                                                                                        else:
                                                                                            reductor = getattr(x, "__reduce_ex__", None)
                                                                                            if reductor:
                                                                                                rv = reductor(4)
                                                                                            else:
                                                                                                reductor = getattr(x, "__reduce__", None)
                                                                                                if reductor:
                                                                                                    rv = reductor()
                                                                                                else:
                                                                                                    raise Error("un(shallow)copyable object of type %s" % cls)


                                                                                        С линейно и прозрачно:
                                                                                        if reductor := dispatch_table.get(cls):
                                                                                            rv = reductor(x)
                                                                                        elif reductor := getattr(x, "__reduce_ex__", None):
                                                                                            rv = reductor(4)
                                                                                        elif reductor := getattr(x, "__reduce__", None):
                                                                                            rv = reductor()
                                                                                        else:
                                                                                            raise Error("un(shallow)copyable object of type %s" % cls)


                                                                                        А ещё теперь можно писать быстрые генераторы comprehension:
                                                                                        [y for x in data if (y := long_running_fucn(x)) is not None]

                                                                                        Раньше нужно было либо делать цикл, либо вызывать функцию дважды.
                                                                                          –3
                                                                                          зачем первом случае делать
                                                                                          reductor = dispatch_table.get(cls)
                                                                                          if reductor:
                                                                                          rv = reductor(x)

                                                                                          когда можно
                                                                                          if dispatch_table.get(cls):
                                                                                          rv = dispatch_table.get(cls)(x)
                                                                                            +4
                                                                                            Вероятно для того, чтобы работало в 2 раза быстрее. Чтобы был ровно один поиск по условному словарю, а не два.
                                                                                            Пример
                                                                                            [y for x in data if (y := long_running_fucn(x)) is not None]

                                                                                            про то же, он позволяет делать действия посчитать-проверить-использовать коротко.

                                                                                            Там, кстати, есть ещё фича с использованием в all() и в any(), которая позволяет вытащить элемент, который заваливает all() или разрешает any() опять же без написания цикла.

                                                                                            Вот ещё типичная ситуация:
                                                                                            check = foo()
                                                                                            while check:
                                                                                                action(check)
                                                                                                check = foo()


                                                                                            превращается в

                                                                                            while check := foo():
                                                                                                action(check)
                                                                                              +2
                                                                                              Вероятно для того, чтобы работало в 2 раза быстрее.
                                                                                              Про два раза вы мягко говоря преувеличиваете.
                                                                                              Большую часть времени будет занимать вызов функции (который гораздо тяжелее, нежели dict.get). Можно это переписать как.
                                                                                              if cls in dispatch_table:
                                                                                                rv = dispatch_table[cls](x)

                                                                                              не все так однозначно
                                                                                              In [1]: %%timeit d = {'ok': lambda: None}
                                                                                              ...: r = d.get('ok')
                                                                                              ...: if r: r()
                                                                                              ...:
                                                                                              The slowest run took 22.09 times longer than the fastest. This could mean that an intermediate result is being cached.
                                                                                              10000000 loops, best of 3: 131 ns per loop

                                                                                              In [2]: %%timeit d = {'ok': lambda: None}
                                                                                              ...: if 'ok' in d:
                                                                                              ...: d['ok']()
                                                                                              ...:
                                                                                              The slowest run took 23.52 times longer than the fastest. This could mean that an intermediate result is being cached.
                                                                                              10000000 loops, best of 3: 84.5 ns per loop
                                                                                            +3
                                                                                            Почему бы не отрефакторить и сделать «Без», но линейно и прозрачно?
                                                                                            reductor = dispatch_table.get(cls)
                                                                                            if reductor:
                                                                                                return reductor(x)
                                                                                            
                                                                                            reductor = getattr(x, "__reduce_ex__", None)
                                                                                            if reductor:
                                                                                                return reductor(4)
                                                                                            
                                                                                            reductor = getattr(x, "__reduce__", None)
                                                                                            if reductor:
                                                                                                return reductor()
                                                                                            
                                                                                            raise Error("un(shallow)copyable object of type %s" % cls)
                                                                                            


                                                                                            Сразу видно повторение структуры
                                                                                            reductor = some_get_reductor_strategy()
                                                                                            if reductor:
                                                                                                return reductor(something_or_nothing)
                                                                                            


                                                                                            Которую частично можно заменить nullable object'ом
                                                                                            def dummy_reductor(*args): pass
                                                                                            
                                                                                            result = dispatch_table.get(cls, dummy_reductor)(x)
                                                                                            if result:
                                                                                                return result
                                                                                            
                                                                                            result = getattr(x, "__reduce_ex__", dummy_reductor)(4)
                                                                                            if result:
                                                                                                return result
                                                                                            
                                                                                            result = getattr(x, "__reduce__", dummy_reductor)()
                                                                                            if result:
                                                                                                return result
                                                                                            
                                                                                            raise Error("un(shallow)copyable object of type %s" % cls)
                                                                                            


                                                                                            И избавиться от повторяющихся if'ов
                                                                                            def dummy_reductor(*args): pass
                                                                                            
                                                                                            result = (
                                                                                                dispatch_table.get(cls, dummy_reductor)(x) or
                                                                                                getattr(x, '__reduce_ex__', dummy_reductor)(4) or
                                                                                                getattr(x, '__reduce__', dummy_reductor)()
                                                                                            )
                                                                                            
                                                                                            assert result, 'un(shallow)copyable object of type %s' % cls
                                                                                            return result 
                                                                                            


                                                                                            Уверен, что код можно еще упростить, если знать контекст.

                                                                                            В list comprehension новая фича выглядит полезной, пока не приходит осознание, что при реальной необходимости её можно реализовать самостоятельно один раз на весь проект:

                                                                                            def transform(iterable, with_transform, and_filter):
                                                                                                result = []
                                                                                                for item in iterable:
                                                                                                    item = with_transform(item)
                                                                                                    if and_filter(item):
                                                                                                        result.append(item)
                                                                                                return result
                                                                                            
                                                                                            result = transform(
                                                                                                data, 
                                                                                                with_transform=long_running_func, 
                                                                                                and_filter=lambda x: x is not None
                                                                                            )
                                                                                            
                                                                                            result = transform(data, long_running_func, lambda x: x is not None)
                                                                                            

                                                                                              –2

                                                                                              Ваш вариант с transform выглядит не pythonic-way, и адекватный разработчик никогда не пропустит такое на ревью

                                                                                                0
                                                                                                Адекватный разработчик узнает ограничения, в которых было написано это решение. Здесь transform решает проблему вызова долгой функции два раза. Если у адекватного разработчика будет более симпатичный вариант решения, то он его предложит, а не будет заворачивать ревью.

                                                                                                  0
                                                                                                  def foo():
                                                                                                      for item in data:
                                                                                                          item = long_running_func(item)
                                                                                                          if item is not None:
                                                                                                              yield item
                                                                                                  
                                                                                                  result = list(foo())

                                                                                                  Без введения новых абстракций, без необоснованного использования лямбд, без создания и модификации временного объекта (списка)


                                                                                                  Не, я конечно понимаю, что можно писать на питоне как на фортране/подставь-свой-вариант, но не в том случае, если его будут поддерживать другие люди


                                                                                                  P.s.


                                                                                                  result = list(filter(None, map(long_running_func, data)))
                                                                                                    +1
                                                                                                    В моём первом комментарии transform использовался вместо нового синтаксиса в list comprehension во всем проекте. То есть предполагалось переиспользование этой функции, а значит нужно либо вводить новую абстракцию, либо везде использовать последний вариант:

                                                                                                    result = list(filter(filter_func, map(long_running_func, data)))
                                                                                                    


                                                                                                    Я согласен, что абстракция не нужна, если проблема, которую решает эта абстракция, не сильно распространена в коде. Просто я исходил из предположения, что проблема сильно распространена.

                                                                                                    Жаль, в python у коллекций нет методов map и filter, чтобы пример выше выглядел читабельнее:

                                                                                                    result = data.map(long_running_func).filter(filter_func)
                                                                                                    


                                                                                            0
                                                                                            Не могу сказать, что я хотя бы раз сталкивался с ситуацией, в которой жалел о том, что такой фичи нет в Питоне.

                                                                                            Я не раз ловил себя на мысли, что хочу такую штуку в comprehension, еще до появления данного pep


                                                                                            Большое количество примеров есть на гитхабе https://github.com/python/cpython/pull/8122/files

                                                                                              +1
                                                                                              поддерживаю. какоето странноватое новвовидение.
                                                                                              вижу смысл только, для while
                                                                                            –42
                                                                                            О нет, PHP грядет, покайтесь говнокодеры
                                                                                              +16
                                                                                              Ув. 4p4, a можно, пожалуйста, фото Гвидо в немного большем разрешении? Мне 1619x2024, к сожалению, не хватает, чтобы рассмотреть подробнее некоторые волоски и поры на коже. :)

                                                                                              А вообще, спасибо за своевременную публикацию новости. Грустно, все стареют, того и гляди, скоро и Торвальдс на пенсию уходить соберётся… Ужс.
                                                                                                0
                                                                                                Игнашевич: «Я устал, я ухожу. Этот чемпионат был последний для меня. Когда-нибудь это всё-равно должно было произойти, в конце концов этот пресловутый автобус всегда таится где-то за углом, а я не становлюсь моложе. (Не буду утомлять списком всех своих проблем со здоровьем).»

                                                                                                Спасибо за статью — узнал для себя создателя Питона.
                                                                                                  0
                                                                                                  Линус, ау!
                                                                                                    +3
                                                                                                    Не дождётесь.
                                                                                                      0

                                                                                                      Да ты гений!

                                                                                                      +16

                                                                                                      Даже не знаю, что сказать. Я не очень пристально слежу за разработкой языка, но честно говоря, я всегда любил питон за некоторую строгость и лаконичность. Мне кажется, что данное расширение не идет на пользу языку, так как позволит писать трудно понимаемые конструкции с большим потенциалом для возникновения ошибок.


                                                                                                      При этом странно: многострочные lambda функции не допускаем, а подобное безобразие не только пропихиваем в язык, но еще и недовольны, что не всем это нравится.

                                                                                                        –6
                                                                                                        if (
                                                                                                                (
                                                                                                                    ( 
                                                                                                                        (a := F1()) and (b := F2(a)) > 100 
                                                                                                                     or (a := F0()) and (b:= F3(a, 0)) > 100 
                                                                                                                    )
                                                                                                                    and ( (c := F2(a, b)) or (c := F3(a, b)) )  
                                                                                                                    and ( res := F4(a, b, c) )
                                                                                                                 or (
                                                                                                                        (a := G1()) > 100 and (b := G2(a)) 
                                                                                                                     or (a := G0()) > 100 and (b:= G3(a, 0)) 
                                                                                                                    )
                                                                                                                    and ( (c := G2(a, b)) or (c := G3(a, b)) )
                                                                                                                    and ( res := G4(a, b, c) )
                                                                                                                )
                                                                                                                and
                                                                                                                (
                                                                                                                    (res := F5(res, a, b, c)) > 1
                                                                                                                 or (res := G5(res, a, b, c)) > 1
                                                                                                                )
                                                                                                            ):
                                                                                                                do_something_with(res) ...

                                                                                                        перепишите на "строгий" питон что-нибудь такое, и посмотрите потом как "лаконично" у вас получится.
                                                                                                        А я такие полуфункциональные конструкты и почище этого видел.
                                                                                                        При том не забываем, что тут на самом деле не a,b,c и Fx, Gx (как тут для наглядности), а длинные говорящие значения.


                                                                                                        Я часто не согласен с решениями Гвидо, но тут его полностью поддерживаю…
                                                                                                        Это как минимум просто удобно (и очень часто нехватало в питоне), спасает от дублирования кода и временных ненужных переменных, ну и тупо необходимая мера, если питон и дальше должен считаться близким к функциональным языком.


                                                                                                        позволит писать трудно понимаемые конструкции

                                                                                                        Это вот-это? Вы серьезно. Какой-нибудь трех-этажный взаимосвязанный декоратор (который даже его разработчик через пол-года не понимает) — это "позволяется", а оператор (оператор, Карл!) всё испортит видите ли… Абракадабру можно написать любыми конструктами в любом языке, это дело личной гигиены и дисциплины (и возможно попустительства ревьюверов, коммьюнити и т.д.). Но никак не отдельного оператора.


                                                                                                        недовольны, что не всем это нравится.

                                                                                                        Всем это простите кому? У вас есть статистика? Многим — возможно, но в моем окружении, это например "всем" поголовно нравится. И что?
                                                                                                        И потом, тут всё просто, не нравится — не используйте...

                                                                                                          +3
                                                                                                          перепишите на "строгий" питон что-нибудь такое, и посмотрите потом как "лаконично" у вас получится.

                                                                                                          Да оно и тут не особо как читаемо, не говоря о том, что дебажить if со сложной иерархией 10 различных состояний — это такое себе… те, кто такой код будут поддерживать — добрым словом автора не вспомнят.

                                                                                                            0
                                                                                                            Вопрос не того как оно читаемо, а если оно именно с такой логикой нужно, как оно будет читаемо если по другому, но… Лаконичнее и проще — не будет. И да то просто один пример, есть и другие — см. выше примеры из раздела Syntax and Semantics.
                                                                                                            +4
                                                                                                            И потом, тут всё просто, не нравится — не используйте...

                                                                                                            Если бы все так просто было. Я вот использовать не буду (условно, лично я не против), а мои коллеги чей код мне потом разбирать — будут. От таких вещей так просто не отгородиться к сожалению.

                                                                                                              0
                                                                                                              Линтер натравите на этот :=
                                                                                                              +2
                                                                                                              Я так понимаю это реальный ваш код?

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

                                                                                                              ну и тупо необходимая мера, если питон и дальше должен считаться близким к функциональным языком.
                                                                                                              Обычно чем функциональнее язык, тем реже в нем используется оператор присваивания. В чистых языка (напр. Haskell), оператора присваивания вообще нету… Но да, для Python это прям необходимоя мера, ага :D
                                                                                                                –3
                                                                                                                ну что можно сказать, месье знает толк…
                                                                                                                  +1
                                                                                                                  Я если честно не совем понял, это вы про свой код?
                                                                                                                  Или вы про ФП, где избегают мутирующих присваиваний (а :=, на минуточку, именно такой)?
                                                                                                                    –3
                                                                                                                    PEP 572 — типичный пример, как много людей забываются, когда начинаются разглагольствования о конкретных деталях синтаксиса… символах операторов, ключевых словах, удобочитаемости и прочих вкусностях.
                                                                                                                    Столько эмоций вокруг деталей синтаксиса тупо не соизмеримы с эффектом от введения собственно этого оператора.

                                                                                                                    Если у человека, после многия доказательства, аргументов и примеров… всего один контр-аргумент типа «говно-код», то вести с ним дискуссию на академическом уровне считаю ниже своего достоинства.
                                                                                                                    Такой ответ вас устроит.
                                                                                                                      +2
                                                                                                                      Столько эмоций вокруг деталей синтаксиса тупо не соизмеримы с эффектом от введения собственно этого оператора.
                                                                                                                      Ну какбы да. Совершенно непонятно, зачем такую фичу пропихивать «против сообщества».
                                                                                                                      Если у человека, после многия доказательства, аргументов и примеров… всего один контр-аргумент типа «говно-код», то вести с ним дискуссию на академическом уровне считаю ниже своего достоинства.
                                                                                                                      Другие примеры неплохи. Хотя из всех только один видится состоятельным — 'while chunk := ...'. Все остальное без особой потери читабельности переписывается без ':='.

                                                                                                                      Насчет вашего примера… Как вам уже заметили «кто такой код будут поддерживать — добрым словом автора не вспомнят». Поэтому я настаивал и буду настаивать, что этот пример можно и нужно называть говнокодкодом весьма посредственным качества.
                                                                                                                        +1
                                                                                                                        Код «с пониженной социальной ответственностью» :)
                                                                                                                        +7
                                                                                                                        Это не один аргумент. Это огромное количество аргументов, которые объединяются под одним названием. В соответствующих рассылках была масса разных примеров плохости этого варианта синтаксиса.

                                                                                                                        Синтаксис и семантика ЯП — это ограничения, которые направляют мысль программиста и облегчают её путь. Если они направят мысли людей не туда (а с новичками так точно будет), то через несколько лет будут большие проблемы у всех.

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

                                                                                                                  +5
                                                                                                                  То, что вы привели — это не код. а ребус.
                                                                                                                    –1
                                                                                                                    Если нужна имменно такая логика (и вам просто повезло что вы никогда такого не видели, хотя в математике, дата-мининге и.т.д и похуже вещи встречаются) — то это не ребус, а всё-таки код.
                                                                                                                    Мой ответ был конкретно на «лаконичность» и «читаемость». Сделать именно такие вещи (хоть ребус, ходь код) более читаемымы и/или лаконичнымы (даже с введением новых сущьностей) не очень получается по видимому…
                                                                                                                    Поэтому и контр-аргументы такие… вида «говнокод» и «ребус». Ну-ну…
                                                                                                                      +5
                                                                                                                      Проблема в том, что даже после введения := код остался ребусом.
                                                                                                                    –3
                                                                                                                    Безпривязки к самой идее оператора :=, чем плохо так:
                                                                                                                    if((a := F1()) and (b := F2(a)) > 100 or (a := F0()) and (b:= F3(a, 0)) > 100):
                                                                                                                        if((c := F2(a, b)) or (c := F3(a, b))):
                                                                                                                            if(res := F4(a, b, c)):
                                                                                                                                do_something_with(res)
                                                                                                                            elif((a := G1()) > 100 and (b := G2(a)) or (a := G0()) > 100 and (b:= G3(a, 0))):
                                                                                                                                if((c := G2(a, b)) or (c := G3(a, b))):
                                                                                                                                    if(res := G4(a, b, c)):
                                                                                                                                        if((res := F5(res, a, b, c)) > 1 or (res := G5(res, a, b, c)) > 1):
                                                                                                                                            do_something_with(res)
                                                                                                                    

                                                                                                                    ?
                                                                                                                    И сразу начинают терзать смутные сомнения насчет условия: ((res := F5(res, a, b, c)) > 1 or (res := G5(res, a, b, c)) > 1). А все ли там так.
                                                                                                                      +5

                                                                                                                      Логика такого масштаба развесистости не имеет права быть реализованной в одном методе. Просто посмотрите на количество "компонентов" — a, b, c, F0, F1, F2, F3, F4, do_something_with(), res, и т.д. Если внутри одного метода действительно такой богатый контекст, это означает, что проблема не в самом методе, а в его окружении. Будет этот метод таким как вы его написали (с новым оператором) или в 3 раза длинее (без нового оператора), разницы совершенно никакой: он хренов бай дизайн.

                                                                                                                        0
                                                                                                                        Так и я восстал против этого тезиса: «перепишите на „строгий“ питон что-нибудь такое». Даже без привязки к необходимости существования оператора :=, небольшие изменения в сторону «канонического» стиля, делают код более обозреваемым, и сразу становятся видны скользкие моменты.
                                                                                                                      +3
                                                                                                                      А вот такой варинат чем вас не устраивает?
                                                                                                                      res = 0
                                                                                                                      
                                                                                                                      if not res:
                                                                                                                        a = F1()
                                                                                                                        b = a and F2(a)
                                                                                                                      
                                                                                                                        if not (a and b > 100):
                                                                                                                          a = F0()
                                                                                                                          b = a and F3(a, 0)
                                                                                                                      
                                                                                                                        if a and b > 100:
                                                                                                                          c = F2(a, b) or F3(a, b)
                                                                                                                          res = c and F4(a, b, c)
                                                                                                                      
                                                                                                                      if not res:
                                                                                                                        a = G1()
                                                                                                                        b = a > 100 and G2(a)
                                                                                                                      
                                                                                                                        if not (a > 100 and b):
                                                                                                                          a = G0()
                                                                                                                          b = a > 100 and G3(a, 0)
                                                                                                                      
                                                                                                                        if a > 100 and b:
                                                                                                                          c = G2(a, b) or G3(a, b)
                                                                                                                          res = c and G4(a, b, c)
                                                                                                                      
                                                                                                                      if res:
                                                                                                                        res = F5(res, a, b, c)
                                                                                                                        if res <= 1:
                                                                                                                          res = G5(res, a, b, c)
                                                                                                                      
                                                                                                                      if res > 1:
                                                                                                                        do_something_with(res) # ...
                                                                                                                      
                                                                                                                        –3
                                                                                                                        Много-много лаконичнее стало, гораздо меньше дубликатов, теперь это конечно много легче поддерживать и развивать, ибо совсем не говно-код…
                                                                                                                        А главное стало так похоже на изначальное математическое-выражение.

                                                                                                                        Т.к. в комментарии тяжело выразить все эмоции — это был сарказм если что.
                                                                                                                          +2
                                                                                                                          А главное стало так похоже на изначальное математическое-выражение.

                                                                                                                          Это в каком таком разделе математики используется деструктивное присваивание?
                                                                                                                            –5

                                                                                                                            Ни в каком (ну почти), просто когда F2(a) может внезапно делить внутри на a (что есть результат от F1), нужно вдруг делать в питоне a and F2(a) чтобы не словить исключения типа ZeroDivisionError.


                                                                                                                            Но выворачивать всё на изнанку и плодить лишние сущности и проверки в угоду "строгому" синтаксису языка (и с потерей читабельности кстати) — это простите нонсенс.

                                                                                                                              –1
                                                                                                                              А почему не вставить в начало определения F2 вот такой код
                                                                                                                              if a == 0: 
                                                                                                                                  return 0

                                                                                                                              ну или
                                                                                                                              if a == 0: 
                                                                                                                                  return None
                                                                                                                                –2
                                                                                                                                Тогда уж хоть `assert` какой-нибудь. Ответ прост — потому что разработчик решил так как решил, ну нельзя её вызывать для 0 и баста.
                                                                                                                                  0
                                                                                                                                  Не положено assert, его оптимизация может удалить
                                                                                                                                    –4
                                                                                                                                    Хот ваших мыслей, и умника ниже, мне понятен…
                                                                                                                                    Вы не поняли мой: я прекрасно знаю для чего assert нужен, но только caller знает что в общей формуле должно проверяется, если результат F1 должен быть в общей формуле больше 20 например, то будет двойная проверка внутри F2 на 0 и в if на > 20.
                                                                                                                                    Результат же один — оппоненты придумывают оправдания и способы обхождения ограниченного синтаксиса…
                                                                                                                                    0
                                                                                                                                    Вы, кажется, путаете ассерты с валидацией, это грубая ошибка. :-)
                                                                                                                              +1
                                                                                                                              Ну как по мне — оба варианта так себе :)

                                                                                                                              Изначально математическое выражение неизвестно, понять что ваш код делает сложновато… Поэтому я переписал его без :=, сохранив структуру.

                                                                                                                              Но да, я считаю что оно стало читабильнее. По крайней мере легче читаются guard-предикаты вида «a and b > 100». Очевиднее как вынести куски в отдельные функции ит.п.
                                                                                                                              навроде
                                                                                                                              def ab1():
                                                                                                                                a = F1()
                                                                                                                                b = a and F2(a)
                                                                                                                              
                                                                                                                                if a and b > 100:
                                                                                                                                    return a, b
                                                                                                                              
                                                                                                                                a = F0()
                                                                                                                                b = a and F3(a, 0)
                                                                                                                              
                                                                                                                                if a and b > 100:
                                                                                                                                    return a, b
                                                                                                                              
                                                                                                                                return None, None
                                                                                                                              
                                                                                                                              
                                                                                                                              def ab2():
                                                                                                                                a = G1()
                                                                                                                                b = a > 100 and G2(a)
                                                                                                                              
                                                                                                                                if a > 100 and b:
                                                                                                                                    return a, b
                                                                                                                              
                                                                                                                                a = G0()
                                                                                                                                b = a > 100 and G3(a, 0)
                                                                                                                              
                                                                                                                                if a > 100 and b:
                                                                                                                                    return a, b 
                                                                                                                              
                                                                                                                                return None, None
                                                                                                                              
                                                                                                                              
                                                                                                                              res = 0
                                                                                                                              if not res:
                                                                                                                                  a, b = ab1()
                                                                                                                                  if a and b:
                                                                                                                                    c = F2(a, b) or F3(a, b)
                                                                                                                                    res = c and F4(a, b, c)
                                                                                                                              
                                                                                                                              if not res:
                                                                                                                                  a, b = ab2()
                                                                                                                                  if a and b:
                                                                                                                                    c = G2(a, b) or G3(a, b)
                                                                                                                                    res = c and G4(a, b, c)
                                                                                                                              
                                                                                                                              if res:
                                                                                                                                res = F5(res, a, b, c)
                                                                                                                                if res <= 1:
                                                                                                                                  res = G5(res, a, b, c)
                                                                                                                              
                                                                                                                              if res > 1:
                                                                                                                                do_something_with(res) # ...
                                                                                                                              



                                                                                                                              PS: Кстати, это так задумано, что функции F2 и G2 могут принимать как 1 аргумент, так и 2?

                                                                                                                                –3
                                                                                                                                Но да, я считаю что оно стало читабильнее.

                                                                                                                                Ну-ну, а что нынче в универах перестали курс булевой алгебры преподовать?...


                                                                                                                                И главное-то мой первый комментарий был ответом на "лаконичнее"...


                                                                                                                                это так задумано, что функции F2 и G2 могут принимать как 1 аргумент, так и 2?

                                                                                                                                А это вас удивляет, в языке как python… def F2(x, factor=1)

                                                                                                                                  +2
                                                                                                                                  Ну-ну, а что нынче в универах перестали курс булевой алгебры преподовать?...
                                                                                                                                  Не могу уловить ход ваших мыслей.

                                                                                                                                  И главное-то мой первый комментарий был ответом на «лаконичнее»...
                                                                                                                                  Если под лаконичностью вы понимаете сугубо размер кода, то в моем варианте аж на 14 непробельных символов больше (не поленился и посчитал). С этой точки ваш исходный код более лаконичен :D

                                                                                                                                  А это вас удивляет, в языке как python… def F2(x, factor=1)
                                                                                                                                  Меня удивляет то, что вы заявляли о «похожести на мат выражение». В мат выражении у вас у функций тоже дефолтные параметры есть? :D
                                                                                                                                    –2
                                                                                                                                    Не могу уловить ход ваших мыслей.

                                                                                                                                    "стало читабельнее"… булева алгебра по видимому для вас не читабельна. Отсюда и вывод.


                                                                                                                                    Если под лаконичностью вы понимаете сугубо размер кода

                                                                                                                                    Под лаконичностью я понимаю то же что и все люди (см. определение в словаре). Это стало менее лаконично. Точка.

                                                                                                                                      +1
                                                                                                                                      До сих пор не понимаю к чему тут булева алгебра. С ней то все ок (я даже использоватл or в своем примере), проблема в «математических» expressions с побочным эффектом.

                                                                                                                                      Под лаконичностью я понимаю то же что и все люди (см. определение в словаре). Это стало менее лаконично. Точка.
                                                                                                                                      Согласен.

                                                                                                                                      Правда изначальный ваш посыл был «теперь это конечно много легче поддерживать и развивать». Согласен, теперь много легче.
                                                                                                                                        +1
                                                                                                                                        Полностью вас поддерживаю, тоже первым импульсом было переписать все на чистых функциях без присвания и дать им нормальные имена из доменной модели, чтобы было понятно, что происходит. На моей работе оригинальный код не прошел бы review, заставили бы переписывать.
                                                                                                                        –33
                                                                                                                        я тоже писал писал opensource потом бросил, неблагодарное это дело! придумывать велосипеды!
                                                                                                                          +12
                                                                                                                          А потом вы получили стрелу в колено?
                                                                                                                          +1
                                                                                                                          На мой взгляд, этот способ присвоения может на порядок понижать читабельность текста. Неудачный PEP, выбранный в качестве последнего перед уходом. Немного противоречит идеям Python. Да и даёт излишний выбор. А чем больше выбора у программиста для одного и того же, тем сложнее будет разбираться в чужом коде. Но в моём частном случае этот PEP может оказаться невероятно полезным, так что может быть это и хорошо.
                                                                                                                            +1
                                                                                                                            Что там понизит читаемость-то? Теперь будет 2 различных оператора присваивания: новый, возвращающий значение присваивания (:=) и классический, не возвращающий значение (=). Не так уж тяжело запомнить, вроде бы.
                                                                                                                              +2
                                                                                                                              Когда с помощью этого оператора наговнокодят… Легко будет вспомнить не только синтаксис оператора, но и много слов, которые мама просила в детстве забыть.
                                                                                                                                0

                                                                                                                                Наговнокодить можно в любом случае. Если использовать := разумно, то иногда можно хорошо улучшить ясность кода

                                                                                                                                  +2
                                                                                                                                  Дело даже не в этом, а в скорости восприятия мозгом информации. Похожие участки кода мозг будет легко воспринимать. Но если сделать две разные реализации одного и того же, то, переключаясь периодически между ними, мозгу потребуется немного больше времени на понимание. Поэтому при командной работе придётся в правилах жёстко прописывать какой вариант присвоения и в каких случаях можно использовать.
                                                                                                                                    +1
                                                                                                                                    Я уже приводил пример выше ;) Скрешиваешь два примера из репа и вуаля — искать ошибку становится весело.

                                                                                                                                    filtered_data = [ z.group(1) if z := re.match(y) else None for x in data if (y := f(x)) is not None]


                                                                                                                                    Хотя тут тоже можно оговаривать ограничения в правилах кодирования: не больше одного сравнения-присваивания в выражении.

                                                                                                                                      0
                                                                                                                                      Ну, вероятно, подобное «быстрое» создание списков будет вообще запрещено. То же самое можно записать обычным циклом с добавлением элементов в список. Помимо читабельности играют роль будущие конфликты при совместной разработке. Шансы на конфликт при изменении одной большой строки будут намного меньше, если её разбить на несколько логически разделённых разных.
                                                                                                                              +1
                                                                                                                              Так, а когда это счастье станет использоваться, следующая мажорная версия питона? Если раньше, то как быть со всей кодовой базой для третьего?
                                                                                                                                0
                                                                                                                                А что не так с кодовой базой?
                                                                                                                                  0
                                                                                                                                  Каюсь, поторопился с комментарием, полез смотреть этот самый PEP, до этого был не в курсе, испугался, что сделали из питона паскаль с этим его :=, но потом вчитался и теперь не понимаю из-за чего весь сыр бор, в отдельных ситуациях жизнеспособная конструкция.
                                                                                                                                +3
                                                                                                                                Ну все? Хороним Питон?
                                                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                    +4

                                                                                                                                    Не-не! Python Classic!

                                                                                                                                      +3

                                                                                                                                      об этом же хотел написать :)
                                                                                                                                      Питон без этого оператора будет называться True Python (рус.: ПитонЪ) ;)

                                                                                                                                        0

                                                                                                                                        Что уж там, сразу Python 4!

                                                                                                                                          0

                                                                                                                                          Python#, по сути, уже давно существует — Iron Python

                                                                                                                                          0

                                                                                                                                          об этом же хотел написать :)
                                                                                                                                          Питон без этого оператора будет называться True Python (рус.: ПитонЪ) ;)

                                                                                                                                            +1

                                                                                                                                            ---камент не туда. как удалить?

                                                                                                                                              0
                                                                                                                                              Да, это известный UX-баг «Хабра», и весьма раздражающий. Комментарий можно редактировать (почему-то только в течение пяти минут — почему не хотя бы сутки?), но удалить нельзя, даже если на него нет ни одного ответа.
                                                                                                                                                +1
                                                                                                                                                почему-то только в течение пяти минут — почему не хотя бы сутки?

                                                                                                                                                Для того, чтобы тролли/спамеры не использовали эту фичу в целях провокации.

                                                                                                                                                  +2
                                                                                                                                                  Тролли и спамеры здесь очень быстро отправляются в минуса, откуда провоцировать значительно труднее (комментарии раз в час; может быть, ещё какие-то ограничения есть), так что это, имхо, не аргумент. А вот невозможность исправить собственную не сразу замеченную ошибку или опечатку расстраивает.
                                                                                                                                                    0
                                                                                                                                                    Больше всего мне нравится как это решено в DeviantArt: можно править долго (год вроде бы), но старые версии сохраняются и доступны.

                                                                                                                                                    Так что все провокации — как на ладони и в бан человека, который редактированием злоупотребляет — как нефиг дела отправить…
                                                                                                                                                  0

                                                                                                                                                  да я даже отредактировать не могу… причём сразу же после публикации… и тут 5 минут мне бы вполне хватило

                                                                                                                                            +4
                                                                                                                                            PEP 572 нужно было отложить в долгий ящик уже давно.

                                                                                                                                            Совершенно не понимаю, почему принимают относительно незначительную фичу, в условиях такого количества разногласий в сообществе.

                                                                                                                                            Даже без учёта самой фичи, решение о принятии само по себе не Python way.
                                                                                                                                              0
                                                                                                                                              Господа, осторожный сахар, который появляется, будь то PEP 572 или PEP 557, который уже в релизе 3.7, к примеру, отлично вписывается в идеологию Python, как мне кажется.

                                                                                                                                              Посмотрите на команду Magic.io (aka MagicStack), последнии контрибуции, в которых они принимали участие — лучшее, имхо, что случалось с языком за последние годы.

                                                                                                                                              Мы, к примеру, в продакшене выжимаем из питона то, что не все могут выжать из Go и ноды. AsyncIO открыл удивительный мир: asyncpg, uvloop, ASGI во все поля через daphne + channels, немного странный APIStar + uvicorn. Python удерживается в топе (а не падает в чистый data science и скриптинг) только благодаря подобным вещам, имхо.

                                                                                                                                              P.S. Yury Selivanov, Elvis Pranskevichus — если вы тут, оставьте комментарий по поводу данного PEP и будущего самого языка, пожалуйста.
                                                                                                                                                +4
                                                                                                                                                Мы, к примеру, в продакшене выжимаем из питона то, что не все могут выжать из Go и ноды.
                                                                                                                                                Статью про это не хотите написать? Уверен, многим будет интересно.
                                                                                                                                                  +4
                                                                                                                                                  в продакшене выжимаем из питона то, что не все могут выжать из Go и ноды

                                                                                                                                                  Если вы умудрились уделать интерпретируемым языком с GIL конкурента без этих ограничений, то мне кажется, что в этом соревновании выступали: Senior Python vs Junior Go.
                                                                                                                                                    0
                                                                                                                                                    Вы правильно поняли мысль, потому и «не все могут»
                                                                                                                                                    0

                                                                                                                                                    Громкое заявление. А можно примеры кода, которые у вас оказались столь быстры?

                                                                                                                                                  +8
                                                                                                                                                  Отлично. Теперь можно будет наконец-то избавиться от GIL.
                                                                                                                                                    +7
                                                                                                                                                    Можно поподробнее для мимокродилов, как уход GVR поможет избавиться от GIL?
                                                                                                                                                    Какие вообще препятствия есть и почему уход Гвидо на это влияет?
                                                                                                                                                      0

                                                                                                                                                      В смысле препятствий есть синхронизация reference counting-а. А гвидо просто всю дорогу говорил, что не выйдет сделать быстрый питон без GIL. Именно из-за сложности синхронизации.

                                                                                                                                                      +1
                                                                                                                                                      Проблема GIL вполе обходится уже много лет, по-моему, давно уже не критично.
                                                                                                                                                        +2
                                                                                                                                                        Зачем обходить GIL? Его специально сделали, а не из вредности. Знаете почему?
                                                                                                                                                          +1
                                                                                                                                                          Почему? И что это? И почему его желают обойти?
                                                                                                                                                          (на Питоне не пишу, потому спрашиваю серьёзно, так как думаю об его изучении)
                                                                                                                                                            +1
                                                                                                                                                            Вот хорошая статья про это: Как устроен GIL в Python

                                                                                                                                                            Что касается обдумывания учить его или нет, то оно точно не должно зависеть от GIL. Вам надо отталкиваться от задач, а не от ограничений языка. Есть задача -> есть условия -> есть язык -> обучение.