Pull to refresh

Comments 304

Грустно, но неизбежно. Непонятно только, почему оставил «разбираться самим», можно же было бы как-то организовать, а то какая-то сознательная организация смуты.
Он же не детей со спичками оставил. Это взрослые люди, в самостоятельности которых он достаточно уверен.
UFO landed and left these words here

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

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

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

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

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


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


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


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


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

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

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


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

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

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

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


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


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

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

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

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


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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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


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


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

Одна программка, опрашивающая сетевое оборудование, на питоне цикл опроса занимал полторы минуты, на гоу без изменения алгоритма стало 4 секунды. Как-то так.
Возможно, если кол-во сетевых оборудований исчисляется сотнями тысяч, но скорее всего программа просто криво написана либо помимо io программа делает кучу вычислений. Питон может обрабатывать до 100krps (и более) в один поток — для опроса оборудования этого достаточно.
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 стало работать заметно медленнее, не критично, но всё равно.
Вы, что-ли, последовательно опрашиваете оборудование?
ssh/snmp можно использовать под asyncio — отправляете команду сразу на 1000 девайсов, через пару* секунд у вас результат с 1000 девайсов.
Если девайсов не так много то можно завернуть готовый синхронный код в потоки (они в питоне настоящие, хотя и с нюансами).

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

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

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


Скорость синглтреда у CPU почти не растёт, тогда как количество ядер растёт. Есть граница, когда более медленный питон приемлим, и когда уже нет. То, что он не поддерживает легковесные треды, а только процессы (со своими ограничениями...), год за годом увеличивает такой разрыв.
Я бы очень хотела появления в питоне хоть и более медленных тредов, чем в Go, но всё же настоящих, а не таких, как сейчас, которые работают только медленнее на любом CPU-интенсив коде. Хочется, чтобы масштабирование было не линейным только из-за закона Амдала, а не по тому, что GIL
Вообще, для численных вычислений эта проблема во многом уже решена, например распараллеливание достигается всего одной директивой:
@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)
А что именно вы имете ввиду под нормальными тредами? Рискну предположить, что речь про Go, но там речь идет про легкие потоки, при которых M горутин отображается на N нормальных потоков ядра. Если так, то честная многопоточность — это достаточно своеобразная задача. Она, к стати, достаточно корошо проработана в контексте асинхронного исполнения кода, и питон максимально близок к, например, Go, в том, что относится к оптимизации исполнения «паралельного» кода, хотя и уступает ему.
Поменять реализацию подсистемы исполнения, чтобы однопоточная реализация питона не потеряла в скорости, при этом появилась возможности исполнять многопточный код — сама по себе задача нетрвиальная. Кроме этого, сто процентов, придется подвергнуть ревизии весь существующий код на питон, потому что старая реализация не подразумевает многопоточность, со всеми вытекающими из этого факта последствиями.
Скорее всего, это и служит препятствием для распространения альтернативных реализаций питон, где с паралельностью ситуация обстоит лучше.
ЗЫ. Я практикую питон начиная года с 2005, и потребность в потоках у меня возникала, от силы, пару раз. Я думаю что прблема отсутствия полноценного массштабирования по ядрам процессора, или по процессорам в случае многопроцессорной системы, имеет место быть, но ее роль сильно преувеличена.
и питон максимально близок к, например, Go, в том, что относится к оптимизации исполнения «паралельного» кода, хотя и уступает ему.


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

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


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

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

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

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

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

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

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

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

Вообще, насчёт «сразу сделать» в ЧаВо 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...

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

При забытом втором символе равенства, будет ошибка.
А если сравнивать две переменных?
> Эммм, а сразу нельзя было сделать

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

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

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

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

Вот например, только сегодня попалась ссылка по C++: gist.github.com/bkaradzic/2e39896bc7d8c34e042b
Там в начале раздела 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)», а потом вернуть её.
":=" и "==" спутать всё-таки трудней, чем "=" и "==". Говорю как человек, многократно проделавший второе.

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

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

Легко, если есть дельфевый проект в конторе.

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

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

if (500 == error_code) {

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

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 будет казаться отлично структурированным и прекрасно читаемым языком)

UFO landed and left these words here
UFO landed and left these words here
Ну не то что бы умер. Занял довольно узкие ниши.

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

Как ни странно 5 лет назад мне предлагали работу на перл, но с зарплатой перловому сеньору, процентов на 40 ниже фронтового миддла) Типа поддержка — это не разработка, так зачем платить много )
UFO landed and left these words here
Просто притока молодежи в перл нет. Приток в дельфи какой-то есть, поскольку в некоторых институтах его возможно «учат» (или уже нет?).

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

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

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

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

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

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

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

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

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

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

Она прочно оккупировала десктоп, так как под неё есть куча всего, буквально миллионы программ (если учесть всякие внутрифирменные поделки). Но… это всё бинарники. Под десктоп. Потому никакие попытки вырваться с этого плацдарма ну хоть куда-нибудь (многочисленные версии Windows NT под разные RISC процессоры, мобильники и прочее) — к успеху не привели.
Погубило 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) таки есть проблемки при переходе между версиями, но где их нет?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

А что с 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».

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

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

Прочитал как ETERNALBLUE… похоже пора завязывать с пентестингом.
UFO landed and left these words here
О, то есть теперь можно второму аргументу функции сразу передавать значение первого?
Вроде
def func(a=(x:=0), b=x):
    return a+b
Мне почему-то кажется, что в такой конструкции x будет нулем, а не значением первого аргумента!
И в самом деле. Ну, может
def func(x:=a, b=x):
    return a+b

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

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

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


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

и


if (diff == a - b):
    doSomething(diff)
Там самый кайф не в таких простых конструкция, а в чуть более сложных, в которых эта техника позволяет избежать от глубоких 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]

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

когда можно
if dispatch_table.get(cls):
rv = dispatch_table.get(cls)(x)
Вероятно для того, чтобы работало в 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 раза быстрее.
Про два раза вы мягко говоря преувеличиваете.
Большую часть времени будет занимать вызов функции (который гораздо тяжелее, нежели 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
Почему бы не отрефакторить и сделать «Без», но линейно и прозрачно?
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)

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

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

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)))
В моём первом комментарии 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)


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

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


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

поддерживаю. какоето странноватое новвовидение.
вижу смысл только, для while
Я вот только одного не пойму, почему нельзя было оставить обычный оператор присваивания, как в PHP if ($holywar_started = true) {...}? Зачем создавать отдельный для этого более неудобый оператор?

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

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

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

Спасибо за статью — узнал для себя создателя Питона.

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


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

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 (как тут для наглядности), а длинные говорящие значения.


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


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

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


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

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

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

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

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

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

UFO landed and left these words here
Я так понимаю это реальный ваш код?

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

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

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

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

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

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

То, что вы привели — это не код. а ребус.
Если нужна имменно такая логика (и вам просто повезло что вы никогда такого не видели, хотя в математике, дата-мининге и.т.д и похуже вещи встречаются) — то это не ребус, а всё-таки код.
Мой ответ был конкретно на «лаконичность» и «читаемость». Сделать именно такие вещи (хоть ребус, ходь код) более читаемымы и/или лаконичнымы (даже с введением новых сущьностей) не очень получается по видимому…
Поэтому и контр-аргументы такие… вида «говнокод» и «ребус». Ну-ну…
Проблема в том, что даже после введения := код остался ребусом.
Безпривязки к самой идее оператора :=, чем плохо так:
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). А все ли там так.

Логика такого масштаба развесистости не имеет права быть реализованной в одном методе. Просто посмотрите на количество "компонентов" — a, b, c, F0, F1, F2, F3, F4, do_something_with(), res, и т.д. Если внутри одного метода действительно такой богатый контекст, это означает, что проблема не в самом методе, а в его окружении. Будет этот метод таким как вы его написали (с новым оператором) или в 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) # ...
Много-много лаконичнее стало, гораздо меньше дубликатов, теперь это конечно много легче поддерживать и развивать, ибо совсем не говно-код…
А главное стало так похоже на изначальное математическое-выражение.

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

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

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


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

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

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

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

Но да, я считаю что оно стало читабильнее. По крайней мере легче читаются 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?

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

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


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


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

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

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

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

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

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


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

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

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

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

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

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

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

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


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

Ну, вероятно, подобное «быстрое» создание списков будет вообще запрещено. То же самое можно записать обычным циклом с добавлением элементов в список. Помимо читабельности играют роль будущие конфликты при совместной разработке. Шансы на конфликт при изменении одной большой строки будут намного меньше, если её разбить на несколько логически разделённых разных.
Так, а когда это счастье станет использоваться, следующая мажорная версия питона? Если раньше, то как быть со всей кодовой базой для третьего?
А что не так с кодовой базой?
Каюсь, поторопился с комментарием, полез смотреть этот самый PEP, до этого был не в курсе, испугался, что сделали из питона паскаль с этим его :=, но потом вчитался и теперь не понимаю из-за чего весь сыр бор, в отдельных ситуациях жизнеспособная конструкция.
UFO landed and left these words here

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

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

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

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

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

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

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

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

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

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

Даже без учёта самой фичи, решение о принятии само по себе не Python way.
UFO landed and left these words here
Мы, к примеру, в продакшене выжимаем из питона то, что не все могут выжать из Go и ноды.
Статью про это не хотите написать? Уверен, многим будет интересно.
в продакшене выжимаем из питона то, что не все могут выжать из Go и ноды

Если вы умудрились уделать интерпретируемым языком с GIL конкурента без этих ограничений, то мне кажется, что в этом соревновании выступали: Senior Python vs Junior Go.
UFO landed and left these words here

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

Можно поподробнее для мимокродилов, как уход GVR поможет избавиться от GIL?
Какие вообще препятствия есть и почему уход Гвидо на это влияет?

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

UFO landed and left these words here
Зачем обходить GIL? Его специально сделали, а не из вредности. Знаете почему?
Почему? И что это? И почему его желают обойти?
(на Питоне не пишу, потому спрашиваю серьёзно, так как думаю об его изучении)
Вот хорошая статья про это: Как устроен GIL в Python

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

PS Спасибо за ссылку!
RIP python. Неплохой был язык.
Linux-kernel на очереди.

Без принципиального и честного лидера любой OpenSource-проект паскудится корпорастами.

Надеюсь, Торвальдс не сбежит так трусливо, а создаст перед этим правила принятия и выпинывания коммитеров, а также жизнеспособные правила выбора диктатора.
а что, правила после их принятия со временем уже нельзя переписать?
UFO landed and left these words here
Ого! Это какая версия потеряла совместимость с предыдущей?
UFO landed and left these words here
dpr файлы всегда совместимы.
а от всяких proj и прочее — никогда обратная совместимость не требовалась.
Уж настроить среду заново при переходе на новую версию — не проблема.
UFO landed and left these words here
Скорей всего использовались сторонние контролы, а в новой версии они уже не поддерживались. Сталкивался с такой ситуацией несколько раз, как правило хватало обычно замены TOldControl на TNewControl по всем файлам проекта, главное было подобрать нормальную замену для контролов.
Я было подумал, что имелся в виду переход на Unicode в Delphi 2010 — вот там действительно полно проблем могло вылезти, а человек про какие-то проблемы с формами, чего я, честно говоря, вообще не помню.

Возможно, имеют в виду переход на Unicode String в Delphi 2009, когда старый тип String (который раньше обозначал строки из 1 байтных символов) начал обозначать строки из 2-х байтных символов. Но при этом Embarcadero очень сильно потрудилась, чтобы облегчить миграцию. Кто не осилил — тот просто плохой разработчик.

UFO landed and left these words here
Ну вот у FreeBSD, к примеру, нет лидера, и за 24 года ни разу не было. Не расскажете, как фря опаскудилась корпорастами?
Породила Mac OS?

P.S>
Это шутка! ШУТКА
Всё-таки NextSTEP на оригинальном 4.3/4.4 BSD базировался, а не на фре. Извините за занудство.
FreeBSD не опаскудили потому, что он не нужен корпорастам.
А как же Juniper (Junos OS), Netflix (OpenConnect), Dell (EMC Isilon), iXsystems (FreeNAS) и др. (наверняка кого-то забыл)?
Ну это ж форки. Корпорасты их и паскудят))))
На днях мы получили патчи Интела для OpenWRT. Как вы могли догадаться — опаскуженные. Какое счастье, что они не имеют привычку обратно контрибьютить к отцам-основателям. Думаю, тоже самое и в мире форков FreeBSD.

Ну вообще Интел один из главных коммитеров в ядро Linux.


Или это у меня детектор сарказма сломан?

Все верно. Только там они не паскудят потому, что их Торвальдс отрезвляет. Я цитирую оценку Торвальдсом коммитов Интела слово в слово:
Complete and utter garbage.

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

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

Чела волнуют различные операторы присваивания, но не волнует отсутствие нормальной многопоточности ;(

Зачем многопоточность в скриптовом языке? Возьмите уже нормальный серверный язык...

UFO landed and left these words here

Casual числодробилка (пример: какая-нибудь аналитика), которая не ложиться на готовый алгоритм в numpy.

UFO landed and left these words here

А этот отдельный сервис на чем будет написан?


На самом деле на любом современном компилируемом строго типизированном языке, от Свифта до Си++, можно такое написать с разницей в эффективности не более 20-30%.

Интересно, а обычное присваивание для чего тогда нужно будет? Везде же можно будет использовать :=?

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

  1. Обычное присваивание — 1 символ, новое два.
  2. Обычное присваивание — тонна существующего ПО.
  3. К тому же сделано всё так, что := используется когда вы знаете что делаете и зачем Вам нужно возвращаемое значение.
Молодец Гвидо. Всем правителям полезно уходить. Вон, из OpenStreetMap ушёл Стив Кост много лет назад, и благодаря этому…

а, кого я обманываю, OSM так и катится в бездну.
9 Кикать — исключать из любого онлайн сообщества, лишать членства.

Да ну? А просто написать «исключать» — никто бы не понял?
3 Менторить — обучать, подсказывать, помогать начинающим во всём разобраться.
— ну, спасибо вам за словарь!
В первом предложении вроде как ошибка в слове «очаянно». Должно же быть «отчаянно», если не ошибаюсь.
Этот оператор присваивания очень бы пригодился в объявлениях переменных. Создаем переменную с помощью ":=", а далее меняем ей значения обычным "=", т.е. если вы опечатались в инструкции "=", это не создаст новую переменную, а вызовет ошибку.
Если вам нравится Go, то вы может уже сейчас использовать Go. Много людей на него, кстати, с Питона и перешло…
Надо кстати рассмотреть этот вариант :-) Но для Python есть привязки огромного числа библиотек, которые легко использовать. Для меня очень удобна простота Python, можно быстро писать прототипы приложений, различные утилиты под конкретную задачу.
Для Go тоже есть немало всего. Перешёл с питона на го и ничуть не жалею. Все задачи были успешно решены на го. Только с немалым профитом в плане скорости, потребления памяти, удобством, что не надо тянуть за приложением весь интерпретатор с библиотеками.
Ну и горутины просто шикарны, заценил, так как много потребностей в этом условно параллельном выполнении.
Нельзя писать на языке только потому, что он нравится. Go и Python — языки под разные задачи. Переход с Python на Go звучит очень странно. На Go можно перейти с C или Rust — это еще куда ни шло.
Переход с Python на Go звучит очень странно.
Это даже Роба Пайка удивило. Он этого не ожидал.

На Go можно перейти с C или Rust — это еще куда ни шло.
А вот и нифига. Это может показаться удивительным, но несмотря на массу формальных различий между Go и Python'ом и формального сходства между C/C++/Rust'ом и Go — на практике Go и Python «живут» в одной нише, а C/C++/Rust — в другой.

Грубо говоря ниша Go и Python — это «мне нужно быстренько маленькую такую приблудку/скриптик сбацать», а C/C++/Rust — это «мне нужен компонент в нашу монструозную мегахрень на 100 миллионов строк кода».

Потому что хотя формально Go и Python могут быть вкручены в другой процесс — но на практике это серьёзная проблема. У них свой, достаточно тяжёлый, рантайм, своё «видение мира» и так далее. Добавление Go и Python'а в проект не написанный на Go/Python — это большое дело.

А вот модуль на C/C++/Rust — можно «прикрутить» к программе на Java, хоть на C#, а можно и на том же Python'е. А вот писать всё программу на C/C++/Rust — часто весьма грустно.

Но это всё теория. Практика же такова: люди гораздо чаще переписывают на Go вещи, которые ранее были написаны на Python'е, чем вещи, ранее написанные на C/C++ (Rust пока слишком молод, чтобы говорить о переходе с него куда-нибудь).
Мотивация создателей Го была сделать язык для больших и огромных корпоративных тимов, с бюрократическим подходом в разработке, то есть в нишу Явы, но нативный. С++ почти подходил, но он очень дорогой в найме и менеджемнте из-за сложности синтаксиса. А корпоративному языку нужны и формализм и дешевизна рабочей силы. Сахар в Го это уже импровизация, заказчику было всё-равно, будет Го похож на Питон, Оберон или на Яву.
Мотивация создателей Го была сделать язык для больших и огромных корпоративных тимов, с бюрократическим подходом в разработке, то есть в нишу Явы, но нативный.
Откуда сведения??? Языков для «копоративных тимов» у Googlе было и есть два: C++ и Java.

А вот для специфичных вещей было создана куча специализированных же языков (самый известный из них Sawzall. Но то, что каждый из них со временем старался развиваться — и появилась идея всё это заменить на один какой-то язык. Который, во-первых, не требует для компиляции часов, а во-вторых — не порождает в результате бинарники на сотни мегабайт.

Сахар в Го это уже импровизация, заказчику было всё-равно, будет Го похож на Питон, Оберон или на Яву.
«Заказчиком» был как бы Роб Пайк, написавший некоторое количество вот этих самых мини-языков. Потом и другие присоединились…
Rust пока слишком молод, чтобы говорить о переходе с него куда-нибудь

По-моему, больше стоит вопрос о переходе на Rust.
Rust и Go концептуально появились почти одновременно. Только скорость развития и достигнутые результаты на данный момент сильно отличаются. На Go чего только не пишут от мелких одноразовых программ до крупных систем. На Rust почти ничего нет.
По-моему, больше стоит вопрос о переходе на Rust.
Сейчас — таки да.

Rust и Go концептуально появились почти одновременно.
Они как бы «заявили о себе» одновременно (да и то — Go в 2009м, а rust — в 2010м). А вот версии 1.0 (после которых только и можно говорить о внедрении) — появились с разницей в три года. Go — в 2012м, Rust — в 2015.

На Go чего только не пишут от мелких одноразовых программ до крупных систем. На Rust почти ничего нет.
Примерно как на Pascal в начале 80х. Тогда и универсайная переносимая среда и первая графическая операционка и много-много всего были на «языке будущего» написаны. Правда кое-то предпочитал Modula-2. И Microsoft и всякие компинии типа Watcom'а именно под него всё делали. И все было уверены, что близкий родственник — это то, куда пойдёт индустрия…

А вот подиж ты: вышло-то по другому.

На Go чего только не пишут от мелких одноразовых программ до крупных систем. На Rust почти ничего нет.
Всему своё время. Если Rust реализует свою задумку и на нём будут писаться модули к C/C++ программам — временный успех Go окажется таким же временным как и временный успех Pascal'я. А если нет — значит нет.
Людям нужны такие языки как паскаль и го. И питон. Простые.
Так то и С++ продолжает развиваться. Даст ли раст такие преимущества, чтобы в него пошли массы разработчиков…
Даст ли раст такие преимущества, чтобы в него пошли массы разработчиков…
Он-то уже даёт. Просто у Rust очень высокий порог вхождения и наверное он этим пугает.
Но для опытных разработчиков на С/С++ должно же быть нормально? Или и для них высоко?
В основном наверное всё упирается в понимание правил владения объектами и получения на них ссылок. И lifetimes. И хотя сами эти принципы довольно просты, я думаю даже опытному разработчику понадобится какое-то время, чтобы подружиться с borrow checker'ом.

И много разных нюансов. Например, в Rust одних только строк 8 видов: {utf-8, c-compatible, os-specific, file system paths} × {borrowed, owned}.

Раньше, когда Rust был в своих первых 1.х версиях, было сложно: и библиотек было очень мало, и всевозможных примеров, гайдов, туториалов. Сейчас эко-система вокруг набирает обороты, и потому уже гораздо проще.
Но для опытных разработчиков на С/С++ должно же быть нормально? Или и для них высоко?
Опытным разработчикам на C/C++ и без того есть чем заняться.
UFO landed and left these words here

Опытные разработчики очень обижаются, что компиляторы не дают стрелять по ногам. Ну вот например, с одной стороны человек делает Option<T> (то есть явно говорит, что значения может не быть), а потом говорит "эх, без анврапа значения не молучить, а я ж точно знаю, что оно там есть".


У меня на самом деле складывается такое ощущение, что новый человек с этими концепциями сживается проще, чем человек с бекграундом С++. Например, я в своих проектах рассматриваю раст как замену моему основному C#, и мне концепции вроде владения дались сильно проще, чем об этом пишут в комментариях специалисты по С++. А ведь это язык с GC где не надо думать про память… Ой, а у нас же есть файлы. А еще сокеты. А еще куча всяких других ресурсов, про который GC не знает и которые приходится костылить через IDisposable. А потом наворачиваем сверху DI чтобы совсем было все приятно.


И поэтому, когда я переписываю код на Rust, где борроу чекер проверит все зависимости, где нет разделения "объект с ресурсами/без ресурсов", где я не получаю NullReferenceExeption в рандомных местах, и где всё приправлено бесплатными итераторами (сколько кушает LINQ можно посмотреть тут) и удобными штуками вроде impl<T> Foo for T, то я испытываю огромное облегчение и удовольствие. И при этом не было какого-то отторжения. Ну да, нужно понять, что есть определенные правила взаимодействия с объектами, но и гарантии, которые появляются в результате этого того стоят. Нужно просто не быть зашореным в имеющемся опыте, а попробовать взглянуть на проблему с другой точки зрения.

> Ну вот например, с одной стороны человек делает Option<T> (то есть явно говорит, что значения может не быть), а потом говорит «эх, без анврапа значения не молучить, а я ж точно знаю, что оно там есть».

Простите, но как автор того комментария, на который вы сослались, вынужден поздравить вас соврамши. Я такого не говорил. Речь шла о том, что если вы в интерфейс своей функции засунули Option, то достать значение из Option-а внутри функции без проверки вы не можете. Поэтому Option в низкоуровневом коде, от которого требуется производительность, вы сможете использовать далеко не везде.

И я очень надеюсь, что здесь сказывается ваше поверхностное знакомство C++ (поскольку вы C#-пер, а не C++ник), а не желание передергивать.
Простите, но как автор того комментария, на который вы сослались, вынужден поздравить вас соврамши. Я такого не говорил. Речь шла о том, что если вы в интерфейс своей функции засунули Option, то достать значение из Option-а внутри функции без проверки вы не можете.


Да. Если вы засунули в интерфейс функции Option, значит он вам может прийти и проверка необходима. Option я буду использовать везде, где он необходим, включая низкоуровневый код. Потому что наприме при передачи референса Option соптимизируется до проверки на null, которую вы бы а С++ в любом случае писали бы. По крайней мере я надеюсь, что писали бы, а не «Да тут null никогда не будет», когда интерфейс функции прямо говорит, что null прийти может.

(поскольку вы C#-пер, а не C++ник)

C#-пер звучит как ругательство :)

И я все еще не понимаю, с чем вы спорите. Если у вас в интерфейсе написать «может прийти null», то функция обязанапроверять на null, нет?
Простите, но вы продолжаете рассуждать о языке, который вы не знаете. Да при этом приписываете мне слова, которых я не говорил.

Я даю прямые цитаты.


Язык отношения не имеет. Я не рассуждаю про какие-то особенности указателей или нужен ли буст. Я обуждаю абстрактные вещи, которые понятны и на псведокоде: если функция принимает тип T?, должна ли она бездумно кастовать её в T? Почему тогда не сделать T сигнатурой?

Я даю прямые цитаты.
Не вижу. Зато виду выдачу своих фантазий за мои слова. Т.е. вранье.
Я обуждаю абстрактные вещи
Слишком абстрактные. Если говорить предметно, то у вас может быть либо так:
fn do_A(v: &Option<Something>) {...}
fn do_B(v: &Option<Something>) {...}
fn do_something(v: Option<Something>) {
  do_A(&v);
  do_B(&v);
}

и тогда у вас проверки будут во всех do_*. Либо можете сделать так:
fn do_A(v: &Something) {...}
fn do_B(v: &Something) {...}
fn do_something(v: Option<Something>) {
  if let Some(value) = v {
    do_A(&v);
    do_B(&v);
  }
}

И проверка будет только в do_something. Если вы пишете низкоуровневый и производительный код, то вы вряд ли выберете первый вариант и, скорее всего, предпочтете второй, в котором у вас Option будет всего в одном-двух местах. Тогда как основная часть кода будет без Option.

Именно это я вам в который раз пытаюсь объяснить.

Это зависит исключительно от того, что внутри do_a/do_b.


Если они логически должны обрабатывать значения Option, то там должны быть Option. Если нет — то нет. И скорее всего будет именно второй вариант, потому что единственный сценарий, при котором подобное может произойти — мы пишем какой-то обработчик, трейт которого вынуждает нас использовать Option и no-op в случае, если значения нет. В случае do_a и do_b таких ограничений нет, потому что это будут приватные функции.

Ну и где в вашем втором примере лишние проверки-то?
Жаль, что прочитав примеры вы не дочитали до этого фрагмента:
… скорее всего, предпочтете второй, в котором у вас Option будет всего в одном-двух местах. Тогда как основная часть кода будет без Option.
Я прочитал ваш комментарий целиком. Но все равно не понимаю почему вы спорите.
Я когда-то смотрел на Rust с большим оптимизмом, но со временем его синтаксис настолько усложнился, что имхо уже затмевает преимущества борроу чекера. Мне неприятно (к моему же сожалению) даже читать такой код, не говоря уже о том, чтобы пытаться на нём что-то писать. :-(
А я учу rust. Пробовал go, но, почему — то, не срослось, после python. Пооблизовался на Nim, но пока боязно за него браться, ранова-то пока.
Гляньте еще в сторону Crystal, думаю самый близкий к питону из компилируемых
Синтаксис Crystal скорее руби подобный, о чем и сами авторы говорят, но это не проблема.
Та же претензия что и к питону — однопоточность. Да, есть файберы, но это одно ядро, и все что из этого следует. Ждать, пока ситуация изменится, я пока не готов. Например глядя на ocaml, который появился в 1985 году, а попытки добавить в него полноценную конкурентность стали предприниматься совсем недавно. Хотя сам язык, на мой взгляд, весьма интересный и достоен большего внимания, чем сейчас реально имеет.
VsCode предлагает какие — то плагины для поддержки crystal, это очень хорошо.
В общем: спасибо за наводку, буду пробовать, что за зверь, и с чем его едят, хотя бы для того, чтобы составить свое представление.
А можете привести пример?
Просто мне кажется, с тех пор синтаксис не изменился сильно. Разве что добавили, например, оператор ?, который заменил макрос try! (меньше скобок и визуального мусора), а ещё (из недавнего) — impl Trait и &dyn Trait.
Помнится, если не путаю, то ли здесь, то ли на ЛОРе была тема, там еще кто-то пошутил, мол, «они пытаются переплюнуть по читаемости Perl?», но сейчас навскидку не гуглится. Во многом это субъективно, конечно, но имхо в «старом» расте (который больше походил на ML с «плюсами») этого самого визуального мусора шума было сильно меньше, а код выглядел проще и чище.

Полистайте растоновости на том же ЛОРе (типа такой), там в обсуждениях народ часто об этом пишет.
Конкретно в этом треде половина анонимусов, похоже, находилась под веществами. Придираться к &8, let и обработке результатов через Result — ну как-то…

Да, я понимаю, если синтаксис в целом не нравится субъективно. Тут уж либо пробовать на нём писать и привыкать (я лично раза 4 его бросал, но всегда появлялось желание вернуться), если нравятся довольно строгие гарантии безопасности, либо забить и пользоваться чем-то другим (никуда не денется C, ещё народ Go любит, хотя они с Rust вроде бы не конкурируют).
Да, пожалуй, не самый удачный пример. Вот еще пара ссылок (справедливости ради, автор там явно оговаривается — мол, понятно, что в каждой избушке свои погремушки, и нужно привыкать).

Ну давайте разберем.


fn main() {
    let x = 1;
    let y = {
        x+1;
    };
    println!("x={:?}, y={:?}", x, y);
}

Тут автор жалуется, то точка с запятой меняет семантику. Да вы что :) А в C++ с его while (cond); {} это совсем не так. И что любопытно, на эти грабли наступают примерно с одинаковой частотой, а именно один раз при обучении.


У концепции "всё expression" в сочетании вывода типов подобные вещи влияют, да, но как видно, и в statement-выражениях подобные вещи применимы. Можно придраться к тому, что вместо ошибки компиляции выводится Unit, но это уже попытка выдать плюс за минус. К этому быстро привыкаешь, и это становится намного более удобно. Например вернуть два значения из разных веток if. Да, в C++ есть ?: оператор, но как только нам нужно сделать какое-то локальное вычисление (или например просто сделать запись в лог branch1-branch2), то сразу встает вопрос — что делать? Обычно тогда переменные объявляют до условия, а внутри просто устанавливают значение. Чем это чревато, думаю, объяснять не надо.


По второй в основном жалуется, что все символы важны. Ну например:


pub fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {


если объясните, в чем сложность этой записи я буду признателен. Пока что я вижу просто функцию, которая принимает 2 readonly-слайса произвоильной длины a b и что-то делает с мутабельным слайсом c.


Ну и последний пример


fn new<'a: 'f>(foo: &'f Foo<'a>) -> Self {
    let foo1: &'f Foo<'f> = foo;
    Context { foo: foo1 }
}

такого кода в реальности вообще не встречал, лайфтаймы в 99% случаях элизится, а в остальных случая мне еще ни разу не приходилось использовать отношение a : b. Но даже если, в чем проблема? Тут чутка генериков + касты. Да, пример страшноватый, но в реальности вы встретите это едва ли чаще, чем template-ошибку на 20000 строк.

такого кода в реальности вообще не встречал
А этот кусок кода выдернут из контекста. В оригинале автор говорит: «which could be written more explicitly as», что как бы подразумевает, что по умолчанию так не пишут.

И из статьи же:
А что бы еще набросить на тему синтаксиса, вот прям скопирую фразу из анонса:
Rust’s trait object syntax is one that we ultimately regret.
Это из раздела про нововведение под названием dyn Trait.
Но автор либо не понял, либо решил умолчать, что это про старый синтаксис, от которого как раз решено постепенно избавляться.

В целом, ходит мнение, что Rust не нравится конкретно C/C++-никам. А те, которые приходят из динамических языков (типа JS, Ruby, Python), наоборот хавают Rust с удовольствием.
И алгебраические типы данных, и паттерн-матчинг.
Гвидо ушел Билл Гейтс пришел.
Python входит в состав Microsoft Visual Studio с 2015. Теперь Майкрософт будет «великодушным диктатором» развития языка.
Microsoft != Билл Гейтс.
Он там не работает.
Смотря на Windows 10… я жалею, что Билл Гейтс там больше не работает.
Ну VSCode же отличный получился, не всё там так плохо.
Всегда удивляюсь, когда говорят о строгости и лаконичности питона.
Может, я чего не понимаю?

Вот пример использования Apache Spark, на Python и Scala:

Python:
text_file = sc.textFile("hdfs://...")
counts = text_file.flatMap(lambda line: line.split(" ")) \
             .map(lambda word: (word, 1)) \
             .reduceByKey(lambda a, b: a + b)
counts.saveAsTextFile("hdfs://...")


Scala:
val textFile = sc.textFile("hdfs://...")
val counts = textFile.flatMap(line => line.split(" "))
                 .map(word => (word, 1))
                 .reduceByKey(_ + _)
counts.saveAsTextFile("hdfs://...")


Что лаконичней?
В Python не устали писать «lambda» каждый раз, и ставить "\" в конце строки? Зачем это?
В scala лишнее слово Val перед переменной означает ее объявление и также то, что ее значение не может измениться в будущем.
(Издержки статической типизации, но это позволяет ускорить выполнение программ и предупреждать ошибки, по сравнению с питоном)

Далее вопросы к синтаксису:
for key in d:
    d[key].sort()


В чем тайный смысл двоеточия, если по идее, должно быть достаточно отступов для формирования блоков кода?
Тоже и с оператором IF.
(Кто нибудь может сказать, что это для того, что бы писать операторы в той же строке, но часто вы в питоне такое видели? )

Далее идут классы.
class Some:
	def __init__(self, id):
		self.id=id


Мы что, на C++ пишем? Зачем двойные подчеркивания в языке высокого уровня?
«def init» никак не прошло бы? Давайте тогда и класс через "__class" объявлять, почему так не сделали?

Ну и напоследок о скорости питона.
Он до 50 раз медленнее scala.
Он значительно медленнее PHP, Javascript. Epic fail.
Скорость выполнения задач обспечивается библиотеками, написаными на C.
И не говорите о PyPy — это не стандатный питон.

Выводы:
Крайне медленный и весьма многословный язык, малоэстетичный.
Если его позиции пошатнутся, всем это только пойдет на пользу. (ИМХО, разумеется)
о скорости питона.
Он до 50 раз медленнее scala.
Он значительно медленнее PHP, Javascript. Epic fail.

А на чём держится его большая популярность?
«Они были первыми», Питон был первым из удобных языков, в те годы люди ещё писали на С, Лиспе, Бейсике и Форте в час по чайной ложке, а тут можно было в одного сложное приложение за пару часов (а не недель) сделать.

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

Ещё не забывайте, что мы живем в эпоху бесплатных языков, а тогда даже примитивный интерпретатор Бейсика или компилятор Семантик С++ мог стоить сотню баксов и тут бесплатный Питон.
В том-то и дело, что не был он первым! 20 лет назад «рулили» Perl, потом PHP, а уж потом Python овладел миром.

И вот как раз в сравнении с ними — у Python'а был и простой понятный синтаксис, и всякие другие плюшки.
Без обид, но просто давно живу, много помню :)

Когда Python уже был (несколько лет), PHP еще было кучкой CGI скриптов на Perl и даже называлось PHP/FI (personal home pages / form interpretator), если кто забыл, а то потом адепты похапни стали этого («home pages») почему-то стыдиться и придумали, что PHP это теперь акроним.

Потом кучку скриптов переписали с Perl на C. И уже потом по сути PHP стало тем, чем его нынче поклонники и знают. Я имею в виду, что написали тройку (заодно избавились от букв FI в названии). Писали ее в 1997, из беты вышла, если мне не очень изменяет склероз, в 1998.

На python уже были тонны всего. Уже была прекрасная версия 1.5. Уже вовсю использовала наука (я познакомился с Python в университете, референсная реализация международного стандарта хранения результатов кристаллографических измерений была на Python, утвержденная международным конгрессом кристаллофизиков, на минуточку).

Господи, уже даже в вебе Bobo Publisher и Document Template были сложены в одну кучу и стали называться Principia, а до переименования в Zope оставалось полпальца (тот же 1998 год). Настоящий application server, объектное хранилище, traversal — в сравнении с кучками php скриптов это был в принципе другой уровень архитектуры, космос какой-то. Другое дело, что разработчики «домашних страниц» (тогда и корпоративные сайты частенько так назывались, так что никакого наброса) люто-бешено любили shared хостинги :)

И тут раз — на хабре пишут, что «рулил» PHP, а «потом появился» Python. Строго наоборот, когда Python уже рулил, PHP только появлялся. Не «появился», а именно «появлялся».
Ну если вы так глубо копаете, то обратите внимание, что даже в вашем рассказе PHP/FI был «кучкой скриптов на Perl'е», а не на Python'е. И так было ещё очень долгое время даже после выхода PHP: Perl был номером один, без вариантов. В основном за счёт CPAN'а. Distutils появились в 2000м году, а PyPI — конец 2002го. К этому моменту PHP «дорос» уже до вполне приличной версии 4.0 и, главное, появился на всех «копеечных» хостингах.

Что и позволило ему вытеснить Perl (а о Python в те времена задумывались разве что эстеты, писавшие инсталляторы или двигавшие науку).

А окончательное забвение Perl'а и отказ от PHP — это уже совсем недавняя история.

Тот факт, что PHP появился сильно позже Python'а и, в общем, долгое время был той ещё поделкой, не меняет того факта, что разработка прошла стадии Perl->PHP->Python, увы и ах… Да хотя бы на TIOBE взгляните:

1998й — Perl(2), Python(23), PHP пока нет
2003й — Perl(3), PHP(4), Python(11)
2008й — PHP(4), Perl(5), Python(6)
2013й — PHP(6), Python(7), Perl(8)
2018й — Python(4), PHP(8), Perl(12)

И тут раз — на хабре пишут, что «рулил» PHP, а «потом появился» Python.
Кто пишет? Где пишет? Не надо только мне чужих слов приписывать, пожалуйтся. Я написал то, что написал… про появление Python'а после PHP и речи нет, речь о том, что долгое время Python был нишевым языком и только совсем недавно вошёл в мейнстрим.

Строго наоборот, когда Python уже рулил, PHP только появлялся.
Увы, но нет. «Рулить» Python начал буквально в последние лет пять. А до этого — он был в том же списке, что и другие всякие полуэкзотические языки типа Scheme или Tcl. Кто-то пользовал Guilde для LilyPond, кто-то писал Portage на Python, а кто-то — Gitk на Tcl — кто во что горазд. А мэйнстримом были Perl и, позже, PHP.
Причем рост популярности Питона совпал по времени со взрывным ростом MOOC курсов. Уж не знаю — связаные это вещи или просто так сложилось
Другое дело, что разработчики «домашних страниц» (тогда и корпоративные сайты частенько так назывались, так что никакого наброса) люто-бешено любили shared хостинги :)

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


А Zope была мега-крутой штукой, просто космос, по сравнению со всем остальным, что тогда было. Но с определенными недостатками. Меня больше всего бесило редактирование TTW, которое в браузерах того времени просто не могло работать нормально. Потом появился ExternalEditor, но это было уже когда эпоха Zope начала клониться к закату.


Ну и ни один проект на Zope почти не взлетел, так как требовалась серьезная квалификация разработчиков. Особенно, когда пошли Plone и Zope 3. Документации толковой не было, книг тоже, все приходилось изучать по исходному коду.


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


Да что там говорить, до сих пор львиная доля сайтов делается на PHP и Javascript, и вовсе не потому, что эти языки имеют весомые преимущества. Скорее потому, что любой может осилив 5 строк введения начать лабать на этих языках сайты, пускай это спагетти-код, пускай там тоннами используются неинициализированные переменные, и т.д. Не требуется знать ничего: садись да пиши.

Что лаконичней?
Вы выкусили маленький кусочек, сравните проект целиком.

Может, я чего не понимаю?
Да, в питоне есть некотрые спортные моменты, но все особенности обоснованы.

Скорости питона как правило хватает для зачад для которых он расчитан.
Одно из главных преимуществ — проекты на питоне разрабатывать быстрее и проще поддерживать, чем на многих других языках.
Скорости питона как правило хватает для задач для которых он рассчитан.
Для каких задач он подходит лучше всего?
Например, для всяких прототипов, где скорость работы менее важна, чем скорость разработки
>Для каких задач он подходит лучше всего?
Для задач, где основне время работы программы проходит в блокирвоках диска\БД\чего угодно.

Например взяли кадр с IP камеры, отдали в OpenCV, ждем результат, дождались и показываем, или взяли ввод полльзвоателя, отбработали, кладём в БД, ждем подтверждения, дождались и отвечаем.
Да, для зачач которые не упираются в cpu (из-за питона): веб (где как считается, основной тормоз — бд), бизнес логика, «скриптинг», «прототайпинг» и т.п., вообщем питон хорош как мастер код — для управления более быстрым (низкоуровневым) кодом. И это большой пласт, если вы не пишите спец. софт, свою бд/сервер (nginx) и т.п. то большая вероятность, что питон вам подойдет.

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

Понятное дело, что хочется «быть здоровым и богатым», но в реальности, обычно, приходится выбирать 2 из 3-х:
* Простой
* Быстрый
* Полезный

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

Кстати я его использую в нескольких проектах когда нужно быстро и много вынимать из кафки, парсить fastavro и перекладывать в influxdb. Даёт прирост в 2-3 раза. И тут проще накинуть воркеров в k8s чем переписывать на компилируемый язык.

UFO landed and left these words here
Вот пример использования Apache Spark, на Python и Scala:
Вау! Вот жто круто! Если использовать библиотеку, написанную и заточенную под Scala — то это, оказывается, удобнее всего делать на Scala.

Вы бы ещё сравнили вызов библиотеке на Pascal'е или что-нибудь подобное.
В чем тайный смысл двоеточия, если по идее, должно быть достаточно отступов для формирования блоков кода?

Если так посмотреть, то и in не нужен. :)