Комментарии 85
В Python внутренние области могут только видеть внешние области, но не изменять их.
wut?
def setup():
global pytest
import pytest
Расскажите, что именно я тут меняю и зачем?
def a():
x = 10
def b():
x = 20 #хотел внешнюю x, но ....
print(x)
b()
print(x)
a()
В питоне недозамыкания, про которые лучше не вспоминать (кроме как в разгар отладки).
>>> def x():
... a=10
... def y():
... return a
... a=20
... return y
...
>>> x()()
20
Эмм, а при чем тут питон, если это обычное замыкание по ссылке?
Func<int> X() {
var a = 10;
int Y() {
return a;
}
a = 20;
return Y;
}
>>> X()()
20
Кроме rust'а, который этот вопрос разрулит как положено. Оно либо move, либо borrow в замыкание, но если значение в замыкании, то пока замыкание живо, значение будет то, какое положили. (как всегда, "если нет unsafe'а").
В расте есть линейные типы, которые запретят сначала отдать a в замыкание, а потом смутировать его откуда-то ещё. Это понятно. Непонятно, почему это преимущество. Я могу легко представить ситуацию, где это будет недостатком, и расторешение будет костылить это через рц рефцеллы, обмазываясь рантайм борровчекингом.
Мне нравится раст, но я не вижу смысла фанатично считать правильным только то, как там сделано.
Ошибки времени выполнения
Ну вот постоянно так, ведь исключительно скриптовые языки старадают от таких проблем? :) Как там борьба с NullPointerException, потомки?
Новые (относительно) языки, вроде Haskell, решают эту проблему: они полагаются на пробелы, но предлагают альтернативный синтаксис для тех, кто хочет обойтись без них.
Хаскель и питон появились в один год, каким образом хаскель стал "новичком"?
Список заменяющих языков тоже странный, раст это системная возня с байтиками, где каждая аллокация имеет целый специальный тип, и идёт война за каждый вызов маллока. В то время как в питоне типичное гцшное отношение "насоздавал объектов — гц разберется". Про го и без меня сказано — в mypy типизация на голову выше, чем у го. Производительность — да, такая себе, но обычно на это и пофиг, особенно когда вся нужная инфраструктура на си написана и импортируется в 1 строчку.
Вот Скала или хотя бы котлин выглядят как замена. Раст и го — не очень.
Ну и странно видеть сравнение "табы против пробелов", у питона ведь хватает реальных проблем, докапываться при этом до синтаксиса...
Скала сложнее, но и награждает она больше, если в ней разобраться.
Хаскель и скала +- одинаковы по возможностям, просто скала еще с сишным синтаксисом, поэтому пугает меньше. Ну и да, хаскель для всяких оперденей имхо вполне себе актуальный язык, было бы желание. Но, чем дальше живу, тем больше вижу, что люди не особо стараются развиваться. Выучил язык, выучил фреймворк — растешь в сениоры-лиды своего языка, в комментах на хабре ругаешь другие языки, рассказываешь как ты 15 лет решаешь задачи на своем языке, всякие изящные решения предлагаешь. Вылезти из рамок привычного фреймвокра и подхода большинство людей даже не пытаются. Многие вообще берут одну технологию тырпрайзную — шарепоинт, например — и всю жизнь пишут этот шарепоинт. То, что они за месяц делают задачу на 1 день (конкретный пример из моей практики) — да пофиг, зарплату то платят. Печально всё это, однако.
Собственно, потому и приходится разводить всю эту тягомотину на месяц под устаревшие платформы, хотя и хочется быстро на новой технологии сделать.
Сейчас даже на Python конференции прибегают любители Go и нагло пиарят свой язык с низким содержанием сахара.
А на конференции по Go прибегают любители Rust, и так далее. Круговорот любителей в природе, ничего нового.
Я Вам априори верю, но чтобы был именно круговорот — то он должен быть замкнутым.
Означает ли это что на конференции по Rust прибегают любители Python ?
Круговорот замкнут во времени, но не в пространстве. Любители го прибегают к любителям питона, любители раста к любителям го, а те, кто прибежит к любителям раста, еще не родились/не стали программировать. Возможно, это будут дети любителей питона.
Прошу прощения за занудство, но круговорот замкнутый во времени должен подразумевать возврат в прошлое что ненаучно.
Да и в описанном Вами примере мы скорее всего имеем отношение к последовательности которую можно формализовать так:
"Если n — новый ЯП, тогда на конференции по n-1 ЯП прибегают любители n"
Да, вы правы.
В моем примере было бы правильно сказать, что круговорот как раз замкнут в пространстве, но не во времени, то есть получается спираль вида:
Где n+m; m=[1,2,3...]
— следующий язык, а gen+l; l=[1,2,3...]
— поколения языков (или программистов).
При этом набегают в направлении, противоположном формированию спирали по времени (то есть n+m -> n+(m-1)
).
Ну это ведь логично, языки ведь развиваются. И набегать со словами "смотрите как проблема которая есть в вашем языке автоматически решается в нашем" это просто щэринг знаний, ничего плохого в этом нет. Либо вы в свой язык затащите похожий механизм (привет лайфтайм чекеру в плюсах), либо перейдете на такой язык. Можно существовать в вакууме, и писать так как писалось и 10, и 20 лет назад, но это не очень эффективно получается с точки зрения затрат и сил, и собственного времени.
И да, и нет.
Да — потому что действительно, обмен знаниями и все такое, важно знать, как это делается у соседей, и брать лучшие практики себе.
Нет — потому что часто другие языки ругают с точки зрения контекста, под который "правильный" язык заточен.
Пример — я работаю с Go и часто вижу обсуждения статей вида "почему Go плох", или "почему мы перешли с Go на X" (впрочем, полно и противоположных статей, но там такого обсуждения не получается, конечно). Из недавнего — переход дискорда с Go на Rust и Elixir.
В итоге ругаемые в том или ином языке (в этом случае в Go) вещи — есть следствия trade-off ради получения выгод где-то еще. Например, GC значительно упрощает работу с памятью с точки зрения программиста (особенно что касается гринтредов), но дает пиковые провалы в производительности, когда этот самый GC отрабатывает. Или там отсутствие дженериков делает возможность компиляции за секунды (очень грубо говоря).
В итоге, большинство критики — это просто "неумение правильно готовить ЯП X". И прийти в питон тусовку и сказать — а вот у нас в Го есть гринтреды, а вы до сих пор кипятите с GIL сидите — неверно, потому что контекст решаемых задач на том и на том обычно разный, и цена этого тоже разная.
В целом, самое главное — взаимоуважение и готовность идти на диалог. Не стоит пытаться впихнуть невпихуемое, но и ругать ЯП за то, что он не подошел для решения задачи, где есть инструмент заточенный под эту задачу — тоже неверно.
Согласен, хотя некоторые трейдофы вызывают недоумение. Например, мне лично непонятно, почему называют благом "быстрый компилятор". Ну ок, он за долю секунды вместо 5 секунд скомпилировал, на что человек потратит это время? А он будет несколько часов руками писать то, что за эти пару секунд сгенерировала бы машина.
Трейдофы гил-негил или там динамика-статика более понятны, и вижу применение и там и там. А вот с "быстрым ничего не умеющим компилятором" представить что-то трудно. Для простых задач даже "тормознутые" компиляторы вроде растового и плюсового отработают за секунду. Для сложных простота оборачивается минусами. В общем, странные позиции бывают.
Отсутствие дженериков — это не только ради скорости компиляции, конечно. Это и необходимость расчета размера в хипе, и много чего еще (я не эксперт в этом вопросе). Более того, насколько я слышал, с момента релиза го появились новые подходы к работе с дженериками, которые мы, возможно, увидим в Go 2.
Что же касается времени компиляции — сравните компиляцию большого приложения на Go и на c++ (условно) — разница намного больше, чем 5 секунд против доли секунды. Особенно при кросс-компиляции на несколько платформ, особенно в пайплайне.
Но дабы не вдаваться в холивар — прелесть Go не в скорости компиляции, да и проблем ему хватает. Как и любому другому ЯП.
Отсутствие дженериков — это не только ради скорости компиляции, конечно. Это и необходимость расчета размера в хипе, и много чего еще (я не эксперт в этом вопросе). Более того, насколько я слышал, с момента релиза го появились новые подходы к работе с дженериками, которые мы, возможно, увидим в Go 2.
Ну, рассчеты в хипе и остальное — это пусть голова у языковой типы болит, я за них их работу руками делать не очень жажду. Один раз сделали — оно работает. Да, есть проблемы при попытке добавить какие-нибудь ХКТ, но лучше уж так, чем никак.
Что же касается времени компиляции — сравните компиляцию большого приложения на Go и на c++ (условно) — разница намного больше, чем 5 секунд против доли секунды. Особенно при кросс-компиляции на несколько платформ, особенно в пайплайне.
Да пожалуйста, все равно задачи у нас меньше 4 часов практически не бывают, 5 секунд из них можно выделить. А вот ловить потом часами проблемы из-за того что где-то в FooBarInt32 фикс сделали, а в FooBarInе64 забыли — куда менее приятно (в контексте тех же обсуждаемых генериков). Смысл ведь в том, что если машина тратит время на это, то она выполняет какую-то работу. Либо вы выполняете её руками (тратя куда больше времени), либо не выполняете вовсе, и работа остётся несделаной (тоже плохой вариант).
Но дабы не вдаваться в холивар — прелесть Go не в скорости компиляции, да и проблем ему хватает. Как и любому другому ЯП.
Согласен, я просто сказал, что некоторые трейдофы понятные, а некоторые вызывают недоумение.
Как большой неофит-фанат Rust'а и застарелый олдфаг-питонист, я точно могу сказать, что Rust и python достаточно далеки друг от друга, чтобы не заниматься конкуренцией.
Оставляя в стороне вопросы производительности, библиотек и компиляции, Rust — это практическая вершина строгости. Т.е. не полный пуризм с зависимыми типами, но настолько близко к пуризму, насколько это полезно.
Python — наоборот. Он практическая вершина расхлябанности. Т.е. не полная расхлябанность с JS-style WTF… Пардон, у нас теперь есть ансибл, который ещё более расхлябан, но настолько к нему близко, насколько это полезно.
Т.е. питон идеальный язык для выразительного и краткого кода. Он допускает неточности и огрубления. Rust — практическая вершина строгости и тщательности. Python позволяет написать быстро и близко к тому, что хочется, а язык будет этому помогать. Rust позволяет написать СТРОГО то, что хотелось так, чтобы комар носа не подточил. Все случаи покрыты, всё учтено.
Я бы сказал, что они очень интересно друг друга дополняют.
Но! Важно еще и место Питона в экосистеме и тулчейн.
Место в экосистеме — интерпретатор с очень коротким циклом написал-запустил-проверил, клей для склеивания вызовов сишных и других библиотек и дружественный интерфейс ко всем фичам компьютера. В этом смысле Питон вытеснил перл и тикл. И называемые в качестве альтернативы языки вовсе не выглядят как замена Питону.
Тулчейн — простой и переносимый интерпретатор с неплохим REPL ну и простой дебаггер. Хотя не уверен, пусть подскажут знатоки но и с этой точки зрения альтернативы выглядят не очень.
Ну там же специально в скобках уточнено, что он новый относительно.
Давайте будем честны, каждый из этих языков в чем-то лучше, чем остальные. Вот там они и будут применяться еще ой сколько.
И питон, и го, и раст заточены под, в целом, достаточно разные ниши. Конечно, они в целом перекрываются, но для написания веб-сайта я бы взял питон, для дата-интенсив вебсервиса взял бы го, а для плотной работы с железом скорее раст.
Все они хороши по-своему, и по-своему плохи. Каждый берет то, что ближе к его задачам и мировоззрению. Заменит ли что-то из этого друг друга — вряд ли это вообще когда-то произойдет. Появятся ли в ближайшие годы ЯП, делающие то же самое, но лучше — да, возможно.
Вот тогда и поговорим.
АПД: минусы от тех кто программирует на питоне? :)
Очередная много буквенная похоронная статья по питону, а пациент все никак не умирает. А от отступов прочь руки, это святое)
Отступы такие плохие, что в скала3 (который дотти) такие отступы упёрли и сделали по-умолчанию) С этими изменениями скала код стал куда читаемее.
Минусы отступного синтаксиса для меня были когда я в нано по ссш правил питоновский файл и с отступами мудрил так что оно криво работало. Но, наверное это все же кривой сценарий использования.
Но пробелы/табуляция как способ задавать вложенность блоков кода для меня просто красный флаг. Еще со времен Фортрана у меня к этому сформировалось четкое отторжение.
Не понимаю, почему это показывают как преимущество для новичков и вообще как какое-то преимущество. Что может быть сложного в скобках { }?
Преимущество скобок — при любом форматировании, любых настройках табуляции, любой операции copy/paste можно однозначно сказать что блок кода не изменил своей вложенности.
Также если функция больше чем размер экрана, можно поставить курсор на одну из скобок, промотать экран и увидеть соответствующую ей открывающую/закрывающую скобку, которую IDE подсветит.
Нет ничего сложного ни в том ни в том.
Более того, если вы используете редактор чуть лучший, чем блокнот, то визуальной разницы нет что там, что там.
То, что у вас отторжение — это чисто вкусовщина, не более. Питон хорош как раз тем, что возводит оформление кода в стандарт — хочешь не хочешь, а не получится писать код абы как (без отступов). Да, в 2020 это может казаться странным, потому что уже у всех есть IDE, которые все как надо выравнивают, но в свое время мне это показалось очень крутой фичей.
К сравнению, у компилятора Go тоже довольно жестки требования к форматированию кода, несмотря на наличие скобок. И это тоже супер удобно, потому что писать код одинаково что так, что так — IDE сама делает отступы. А вот читать исходник без отступов (в тех ЯП, которые это допускают, и у тех программистов, кому религия не позволяет) — это просто пытка.
Кстати, по моему преподавательскому опыту, отступы новичков скорее запутывают, скобочки более понятны. А вот читать Питон приятнее и (главное) легче, чем «скобочные» языки.
А каким образом скобки не будут бить по рукам? Фигурные скобки это всегда уровень отступа, некоторые IDE даже ругаться будут и автоматически отформатируют при первом возможном случае (при написании точки запятой, при закрытии скобки, ...).
Не всегда программирование происходит в IDE, по крайней мере для Python. Довольно часто приходится и по ssh и vim что-то подправить.
Без точки с запятой в большинстве япов с фигурными скобками у вас код не скомпилируется.
Ну а без IDE скобки уже удобнее, я выше уже писал. Заходил на ссш, ставил 11 пробелов вместо 12, на меня интерпретатор потом орал, приходилось снова файл открывать и искать, где там косяк
@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
Да даже массивов есть несколько вариантов в широкоиспользуемых библиотеках (numpy, tensorflow, был theano), и они друг с другом не совместимы.
UPD: не заметил, что пост не новый — в сайдбаре был.
Так вот, Python с jit компиляцией по скорости был на уровне C, Go и Rust. Поэтому миф о медленном Python давно уже пора забыть. Правда тут в другом.
На Python можно писать медленно, но в 2020 году нет никаких проблем оптимизировать критические участки кода парой аннотаций для jit комплиции.
Программирование на Python научных задач сейчас во многом иерархично. На верхнем уровне вы концентрируетесь только на сути задачи, не тратя ограниченные ресурсы головы на сугубо технические вещи. После того, как алгоритм готов, критические части обычно можно переформулировать на языке линейной алгебры, что дает а) гораздо более понятный во многом декларативный код и б) производительность близкую к C. Но если что-то сложно ложится на язык линейной алгебры, тогда ладно. Надо добавить типы и выполнить jit-компиляцию.
Поэтому с точки зрения скорости разработки и производительности конечного года Python сейчас во многом уникальный инструмент.
Не говоря о том, что почти любая научная C/Fortran библиотека имеет обвязку на Python. И как дополнительный бонус крайне удобные Python ноутбуки и вменяемая система управления пакетами.
Но, по большому счёту, скорость не имеет решающего значения. Производительные компьютеры и серверы настолько доступны, что речь разве что идёт о долях секунды. Конечному пользователю все равно, загружается его приложение за 0,001 или же за 0,01 секунды
Личный опыт — писал скрипт, который производит итеративный (2000+ итераций) расчёт на данных размера 4095x4095. Питон считал результат более 5 часов. Не помогал ни numpy с массивами вместо списков, ничего. После переписывания скрипта на C++ с задействованием GPU время расчёта уменьшилось до 4 секунд.
Производительность важна.
С другой стороны, объявления переменных и операторы всегда являются операторами. Это означает, что лямбды не могут быть использованы для них.
Это различие между выражениями и утверждениями довольно произвольно и не встречается в других языках.
Не очень понял этот пассаж. То ли ошибка перевода, то ли что-то пытались сказать…
Да и вообще наезд на лямбды какой-то натянутый, они работают как анонимные функции by design.
Если вам нужно создавать новую переменную — сделайте полноценную функцию, не нужно пристраивать крылья к велосипеду.
Вместо этого код компилируется всякий раз, когда исполняется, поэтому любая ошибка в коде проявляется во время выполнения программы.
А как же .pyc файлы?
Поэтому да, то что раньше играло в плюс, со временем может играть уже и в минус.
Не «что в Python мне не нравится», а «что изменилось вокруг Python так, что он перестал отвечать потребностям».
Вот например, он критикует отношение Python к пробелам и табуляции. Что где поменялось так, что пробелы и табуляция раньше не были проблемой, а теперь стали?
Питон медленный. Не, ну реально медленный.
У Python прекрасная двусторонняя интероперабельность с C и C++, о которой никто из конкурентов не может и мечтать. Это основная причина его успеха. Именно благодаря ей существуют NumPy и подобные пакеты. И если уметь ей пользоваться, то на выходе получишь высокую скоростью разработки с не менее высокой скоростью выполнения.
Несмотря на всю гибкость Python, использование лямбда довольно ограничено. Они могут быть только выражениями в Python, но не операторами.
Ну, то есть они именно лямбды, в исконном значении этого термина, а не просто анонимные функции, как в других языках.
Хотя это может не так красиво и неудобно для начинающих, это делает код более удобным для сопровождения.
С чего бы это вдруг?
Python не был создан для мобильных устройств.
Go и Haskell заточены?
Вместо этого код компилируется всякий раз, когда исполняется
Это не так. CPython компилирует код при первом выполнении. Можно скомпилировать и до.
У меня сложилось впечатление, что автор оригинала считает статическую типизацию однозначно хорошей, а динамическую однозначно плохой. Что, конечно же, ужасная глупость. Инструмент надо выбирать под задачу. Поэтому существование таких языков, как Rust не угрожало и не будет угрожать существованию таких, как Python.
Ну, то есть они именно лямбды, в исконном значении этого термина, а не просто анонимные функции, как в других языках.
Мне почему-то кажется, что лямбда-счисление разрешает объявлять переменные, а лямбда в питоне объявить переменную не разрешит. Так что я бы не стал говорить, что именно в питоне исконные лямбды.
Вот как раз лямбда-исчисление никаких переменных не разрешает. Это ж чистое ФП, притом настолько чистое насколько это возможно — там нет вообще ничего кроме функций, даже стандартных типов данных, вроде bool или int (они все выражаются через функции).
То есть понятия "лямбда-абстракция" не существует или оно означает не то, что я думаю (биндинг имени к некоторой функции)?
Lambda calculus (also written as λ-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution.
f(x,y)=x+y — функция двух переменных.
PS: слово «binding» читается через «ай».
Слово «переменная» в математике имеет несколько иное значение, чем в программировании.
f(x,y)=x+y — функция двух переменных.
Возьмём даже такой приземлённый язык как жс и получим
const f = (x,y) => x + y;
Как по мне, это — переменная.
Впрочем, это не важно, я вполне четко имел в виду лямбда абстракцию когда писал оригинальный комментарий. Покажите, каким образом "Лямбда абстракция" выражается в питоновских лямбдах, и это в принципе ответит на вопрос, и не надо будет вести полемику на тему "а являются ли функции как объекты первого класса переменными".
PS: слово «binding» читается через «ай».
Знаю, просто иногда почему-то приятнее использовать такое слово. Как "адоб" вместо "эдоуби" и "зиксель" вместо "зайзел".
То есть понятия «лямбда-абстракция» не существует или оно означает не то, что я думаю (биндинг имени к некоторой функции)?
Нет, λ-абстракция — это создание из выражения, содержащего переменную x, функции этой переменной. (То же самое написано на рувики.) Это в точности то, что делает оператор
lambda
в Python.PS: ладно что не «зухель»
1) пайтон для ИИ/Нейронок и тд… (вот его стихия)
2) пайтон быстрее чем с++ в 14 ра => (Вот взяли 1 задачу и сказали программистам реализовать ее. Самое быстрое решение было за 2 часа на питоне, самое долгое за 14 часов на срр. Мораль ,, в первой версии стартапа можно ложить боль на много вещей. Нам важно чтоб продукт был сделан в кратчайщие сроки и если он будет перспективным — мы будем расширять функционал, оптимизировать, использовать другия ЯПы,, ну и как следствие бюддет на разработку можно скоратить в 7 раз. И эти деньги перераспределить на маркетинг
3) все уходит в мир облачных вычислений. (Зачем мне делать приложение на разные платформы, если я 1 раз сделаю логику на сервере и красивый UI на разные платформы с минимальным функционалом)
ИМХО.
проблемы выглядят высосанными из пальца.
медленный? последствия динамичности и сложности оптимизации, решается JIT в PyPy. хочешь еще быстрее — пиши модули на C
нет явного объявления типов нужно много тестов для отлова ошибок? аннотируешь код и подключаешь анализатор вроде mypy
не подходит для мобил? успешные реализации есть — renpy неплохо себя чувствует в сфере игр. интерпретатор давно перетащили на множество платформ, просто никто еще не релизнул серьезную библиотеку для UI
Строгие отступы делают код читабельнее, но их обязательность ухудшает поддерживаемость.— бред
Почему будущее не за Python