LINUX.ORG.RU

Объектная модель питона

 , ,


2

4

- Сколько нужно архитекторов, чтобы создать язык программирования?
- Сто. Один будет писать язык, а 99 - говорить, что могут сделать лучше.

Так скажем, я решил вспомнить обсуждение по теме треда: Generics в Python или помогите победить mypy

Да, наркоманский питон захватывает мир, и с этим нужно что-то делать. Нет, я не намерен делать питон 4 - я вижу свет в конце тоннеля в рамках третьей версии. Но мне нужна ваша помощь: какие фундаментальные фичи, по-вашему, в питоне вообще не нужны, а какие - должны быть переработаны?

Прежде всего, я хотел бы вспомнить про RPython ( https://rpython.readthedocs.io/en/latest/rpython.html ).
Смысл особенностей языка прост - поддержка вывода типов. В частности, из языка убраны динамические определения классов и функций, динамическая типизация переменных, глобальные переменные стали константами, функции-генераторы транслируются в классы-итераторы и потеряли большую часть своих фич. У RPython есть большой минус - эти его ограничения сильно раздувают код, затрудняют писание и читание.
Итак, мои соображения:

1. Множественное наследование. Его нет даже на уровне C-функций в реализации питона и API расширений. «Но как же интерфейсы?» - возразите вы. Интерфейсы в C++ и Java нужны в роли объявления протоколов вызова методов объекта с целью последующей статической проверки этих протоколов при компиляции, а также для формирования таблиц методов, которые можно использовать независимо от объекта во время выполнения. Эти роли полностью потеряны в питоне, потому нет никакого оправдания их существованию. Мне нравится то, как сделаны интерфейсы в Go - это очень похоже на питоновые ABC: https://www.python.org/dev/peps/pep-3119

2. Генераторы - зло. Это прямо-таки запущенный случай GoTo, когда выполнение не просто бесконтрольно прыгает по коду - оно прыгает по стэкам. Особенно лютая дичь происходит, когда генераторы пересекаются с менеджерами контекста (привет PEP 567). В треде, скорее всего, опишу веселости реализации генераторов в PyPy/RPython. В питоне есть общая тенденция запутывать приложение в тесный клубок связанных изменяемых состояний, что не дает возможности параллелить и оптимизировать выполнение программы, а генераторы - вишенка на этом торте.

3. Изменение классов для существующих экземпляров объектов. Не, я понимаю, что класс в питоне объявляется во время выполнения. Но, блин, зачем в него совать изменяемые переменные? Зачем в старые объекты добавлять новые методы? Причем, попрошу обратить внимание на то, как нужно нагибаться раком для того, чтобы добавить аналогичные методы в сам объект, а не в класс - для этого нужны types.MethodType, function.__get__, functools.partial, и так далее. Методы в питоне вообще понадобились по простой причине - гвидо не придумал других способов сделать короткие имена функций (чтобы не было gtk_button_set_focus_on_click), поскольку не ясно, как выбирать из кучи похожих функций с коротким именем нужную под этот конкретный объект. Так в питоне появились len, iter, next, isinstance, slice, dict, dir, str, repr, hash, type - сейчас это обертки над соответствующими методами классов с подчеркиваниями в имени, а когда-то встроенные простые типы не являлись классами и работали только через эти функции. Так-то, я не вижу особой разницы между записью method(object) и object.method - особенно если method является статичной функцией, которой, в общем-то, все равно, какой первый аргумент (self) принимать.

Вот. Прошу дополнять. Да, я знаю, что у питона основные проблемы две: отсутствие статической типизации и многопоточности - но это черезчур абстрактные требования. К тому же, Javascript безо всяких типизаций достиг производительности Java, при том, что жавамакакам постоянно приходится гнуться под язык, а JS-кодеры испытывают удовольствие от говнокодинга.

★★★★

Ответ на: комментарий от system-root

раз вы такие умные, почему тред читать невозможно и ощущение, что это батл wiki-ботов?

Вики-бот - это, по большей части, лизка.
Если говорить про конкретно меня, то на эрланге/эликсире я писать не умею, но знать общие архитектурные решения эрланга для меня важно по тем или иным причинам. Поэтому статей и исходников компиляторов/рантайма/библиотек для эрланга, жавы, го я читал намного больше, чем писал на самих этих языках.

единственный коммент который не похож на высер бота: ... - успешно проигнорирован.

Я ответил: Объектная модель питона (комментарий)

небыло нормального евентлупа, небыло евентбаса

Дефайн «нормальный евентлуп» и «нормальный эвентбас». Промисы в питоне есть, но называются по другому. Собсна, в JS они теперь тоже называются по другому.

небыло нормального orm, не прибитого гвоздями к web(sic!) фреймворку

Абстрактные объекты/ассоциативные массивы тебе никто не запрещает использовать. Но оживают и приобретают смысл они только при взаимодействии с конкретным применением.

из «реактивности» там был этот asyncio написанный двумя идиотами

Ты не понимаешь смысл понятия реактивности. Asyncio - это либа асинхронных событий, для реактивности же нужен некие интерфейсы с интенсивным инкрементальным вводом и выводом, пусть и не обязательно пользовательский интерфейс.

byko3y ★★★★
() автор топика
Ответ на: комментарий от n008_b4800n

Потому что в консоли объект генератора не умрет, и finally не будет вызван. finally тут работает, как деструктор. Генераторы не причем.

Да? А как тебе такой аргумент?

import contextlib
@contextlib.contextmanager
def context_manager():
    try:
        print('Вход')
        yield
    finally:
        print('Выход')

def gen_in_manager():
    m = context_manager()
    with m:
        return (i for i in range(5))
				
g1 = gen_in_manager()
next(g1)
print('Конец')
Вход
Выход
Конец
А ведь это тоже генераторное выражение.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

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

Задефайнить можно приведя в пример ноду, или vertx.

system-root ★★★★★
()

отсутствие статической типизации и многопоточности

Пиши на хаскеле/ржаве/идиязе/пр. - где этого с избытком. Батареек не хватает – так интереснее/проще написать/дождаться нужного там, чем починить всё тут.

DonkeyHot ★★★★★
()
Ответ на: комментарий от Shadow

Не все умеют думать асинхронно. Даже наоборот. А программировать хочется.

Не все умеют ходить на руках, а ходить как-то надо. И тут разветвление: люди сидят и думают как все-таки ходить ногами асинхронно (изобретают CSP), а макаки надевают модные кеды на руки и поскакали. При этом улюлюкают и строят рожи остальным, кто не хочет прыгать на руках.

anonymous
()

Пиши на хаскеле/ржаве/идиязе/пр. - где этого с избытком. Батареек не хватает – так интереснее/проще написать/дождаться нужного там, чем починить всё тут.

На хаскеле пишу - говно ваш хаскель. Это чисто академическая хрень для написания научных работа и бесконечного оргазмирования над красотой модели, которую ты придумал для решения задача, пока мартышки уже пять подобных задач решили и пошли дальше.
«Идияз» - это кто? Идрис?
От джавы лично я довольно далек. Хз, почему ты не упомянул свифт, го, эликсир/эрланг. На JVM еще есть куча языков, более адекватных, чем сама жава.

byko3y ★★★★
() автор топика
Ответ на: комментарий от x3al

Если у тебя ML — там собственно питона не так много и тот же гугль давно продвигает использовать swift вместо питонов в том же tensorflow для тех, кто хочет нормальные типы...
В питоне взять [0] от потенциально пустого списка — вообще не проблема

Блин, я тут сижу и пытаюсь сообразить, что можно с этим сделать в рамках питона. Легко быть как Кернес: https://www.youtube.com/watch?v=zddj4BA_7OM
Основной механизм, которым хаскель, свифт, лисп, раст, а ныне уже частично и жава с крестами, позволяют не указывать тип, но при этом иметь идеально статические типы - это вывод типов на основе использования переменной. То есть, нужно собрать в кучу всё использование ячейки и придумать ей свойства. Но проблема в том, что ни всевидящий Аллах, ни Господь Саваоф не знают всех вариантов входных данных, которые переварят функции стандартной библиотеки - а ведь это фундамент.

pytype пытается сделать именно вывод типов для проверки корректности кода, что есть похвально, но не поможет в REPL, или ту же стандартную библиотеку вывести не сможет из-за слишком размытых типов онной. Взять тот же итератор, который может быть с __iter__, но может быть с __getitem__ — оба варианта корректны для цикла for.

Неужели ни у кого нет никаких идей? Вот например, статичные описания классов позволяют выводить атрибуты у ячеек и проверять корректность работы с объектами по единому интерфейсу, то есть, по ABC-стилю. Если же на каждый объект во время выполнения еще и вешать критерии корректности работы с этим объектом, то можно в специальном режиме отладки увидеть те ошибки, которые в норме ни статические валидаторы, ни сам CPython выловить не смогут. Например, какой-то отбитый код (не метод объекта) решает добавить свой собственный атрибут в объект - по ошибке или из-за плохого стиля. И тогда валидатор сможет выдать предупреждение, мол, «нарушение инкапсуляции». Или в ячейке лежит строка, но какой-то кусок кода может потенциально положить в ячейку массив - вуаля, получите ошибку в консолю. То есть, по сути это то, что делает JIT-компилятор, только на этот раз JIT-компилятор в явной форме высказывает свои возражения по поводу неоптимизируемости куска кода.

Есть смысл для таких танцев заставлять кодеров объявлять переменные динамического типа явно (val1: Any или val1: Union[list,str]), а жестко ограничиваемый статический тип будет выводиться неявно. Естественно, нужно еще переосмыслить само понятие «тип», чтобы под ним подразумевался абстрактный класс, как с тем же итератором, а не конкретный.

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от anonymous

Го? Жаба… Да вы с дуба рухнули. Скала возможно да. И кстати я старый хрен писал и на Го и на Жабе. Более того на жабе писал до Пайтона. И это боль.

dem ★★
()
Ответ на: комментарий от byko3y

Перевожу взад

для написания научных работ

Откуда я знаю, для чего тебе перепитон.

это кто

идияз, ржава

от джавы лично я довольно далек

Ты, вроде, недостатончо нагадил, чтобы быть туда посланным:)

DonkeyHot ★★★★★
()
Ответ на: комментарий от byko3y

Есть смысл для таких танцев заставлять кодеров объявлять переменные динамического типа явно

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

anonymous
()
Ответ на: комментарий от anonymous

Ты посмотри современные языки типа scala, crystal. Там нет ни капли динамической дристни, но абстракции на уровне пистонорубей. Метапрограммирование тоже статическое на макросах.

Clojure еще из той же оперы. Лет через десять Crystal посмотрю. Знаешь почему? Потому что производительность у него на уровне питона (внезапно https://github.com/kostya/benchmarks ), батареек нету, а динамичность находится на уровне жавы, которая тоже умеет оперировать не до конца ясными типами, вроде стирания типов в списках. Если бы я писал проект с нуля сам или с молодыми макаками, то я бы подумал про кристал. Но я не пишу ничего с нуля, и не буду писать. А вот шанс удостоиться чести докинуть костыль в гору костылей у меня есть вполне реальный.

Метапрограммирование тоже статическое на макросах. Динамика не нужна, давно пора это понять и закопать уже стюардессу.

Питон тоже статически компилируют - проблема как бы не в этом, а в том, как поддерживать и дорабатывать крупный проект. Очень просто сказать «давайте просто всё выкинем и перепишем заново». Джангу и тензорфлоу ты будешь мне на кристал портировать? Или вот эти ребята? https://github.com/fazibear/tensorflow.cr

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Crystal (пока?) не для того, чтобы на нем писать, а чтобы продемонстрировать как можно совсем без динамики получить то же, что и в ультрадинамичных рубях. Чуваки, которые его делают так и сказали: мол по фану решили замутить такое. А потом их внезапно профинансировали на фултайм разработку. Насчет бенчмарков этих ты прикалываешься что ли? Или ты сишные реализации numpy и ujson узрел в топах? Лол. Я считаю, что бенчмарки мусорные, но по ним как раз с кристалом все ОК. Хотя в жизни не все так гладко, понятно.

anonymous
()
Ответ на: комментарий от byko3y

Kotlin еще на слуху. Хотя я не знаю, что там с макросами. Без AST макросов понятно это все ненужно, можно на жаве просто писать.

anonymous
()
Ответ на: комментарий от anonymous

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

Эти люди просто в сотый раз изобретают лисп. Я имею в виду статически комплируемый лисп, со статической проверкой типов при компиляции и макросами во время компиляции, а не полную динамику. До людей за 50 лет так и не дошло, что это лучший вариант высокоуровневого программирования. И не дойдет. А значит, писать ты будешь на том, на чем пишут все макаки. В том числе макаки из гугла, ютьюба, и дропбокса, которые, внезапно, пишут на питоне.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

писать ты будешь на том, на чем пишут все макаки

Сейчас передовые макаки на дарт, котлин и свифт наяривают, всяко лучше пистона. Вообще любой ЯП, где компилятор помогает (а не сношает тебя в голову как плюсцы или раст) лучше пистона.

anonymous
()
Ответ на: комментарий от eternal_sorrow

2020 на носу, «гендер — социальный конструкт», все дела. Ты отстал от жизни. Говорит, что баба, значит баба, и не важно какой длины у неё борода.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Отрицание одного социального конструкта путем навешивания на себя другого - это как в целях профилактики ВИЧ подцепить сифилис.

cherry_boy
()
Ответ на: комментарий от byko3y

vba

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

anonymous
()
Ответ на: комментарий от cherry_boy

Нет, это я понял.

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

что есть один социальный конструкт и что есть другой?

eternal_sorrow ★★★★★
()
Ответ на: комментарий от eternal_sorrow

И баба, и мужик в отрыве от половых признаков суть есть социальные конструкты, которые определяют их поведение. Грубо говоря, если бородатый дядька лупит жену, пьет пиво и перебирает в гараже рыболовные снасти - это традиционная ролевая модель, если готовит ужин, ходит на балет и смотрит мультики про розовых пони - нет. Ради бога, собственно, но когда они самоидентифицируют себя как мужчину или женщину, они сами же на себя навешивают определенный ярлык, что в случае ортодоксального мужика в семейниках еще может быть естественно, а в остальных уже странно, ведь если ты признаешь право отойти от принятой модели поведения, то должен понимать и всю нелепость высказываний «я мужчина», «я женщина», «я хоббит». В таком случае каждый из нас просто человек, ни больше, ни меньше.

cherry_boy
()
Последнее исправление: cherry_boy (всего исправлений: 1)
Ответ на: комментарий от cherry_boy

отойти от принятой модели поведения

Собственно, а кем принятой? Что выделяет эту модель среди прочих? Почему, отказываясь от каких то заскорузлых понятий я также должен отказаться от всем понятных обозначений?

eternal_sorrow ★★★★★
()
Ответ на: комментарий от anonymous

дарт

Пока что только внутри гугла используется.

котлин

Да, апгрейд жавы для андройда.

свифт

Да, апгрейд объектного си для айфона. И таки выглядит получше всего из этого списка трех вариков, хотя бы потому, что на этом кто-то пишет и это не компромис.

а не сношает тебя в голову как плюсцы или раст

Страуструп пытался сделать лисп в Си. Вывод типов по Хиндли-Милнеру был известен уже в 1982-1985, до выпуска C++, но упрощенный lambda calculus был известен еще со времен первого лиспа, так что никаких оправданий у создателей крестов, жавы, и тем более дотнета, нету - они высрали дерьмо. Это к слову о том, насколько медленно и неохотно развивается IT. Даже, казалось бы, во время бума 90-х. В итоге, популярность получает то, что быстрее зарелизят и поддержат крупные игроки. Да, все вы будете писать на дарте... но лет через 10, не сейчас, даже несмотря на то, что сейчас дарт нужен намного больше, чем будет нужен через 10 лет.

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

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

упрощенный lambda calculus был известен еще со времен первого лиспа, так что никаких оправданий у создателей крестов, жавы, и тем более дотнета, нету - они высрали дерьмо

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

byko3y ★★★★
() автор топика
Ответ на: комментарий от eternal_sorrow

Собственно, а кем принятой?

Обществом.

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

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

cherry_boy
()
Ответ на: комментарий от byko3y

попытайтесь, пожалуйста, придумать, можно ли чем-то помочь горбатому.

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

anonymous
()
Ответ на: комментарий от anonymous

Расставить аннотации везде по стандартным батарейкам

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

Весь манкипатчинг убирать где найдешь.

За это вообще нужно руки отрывать. Но часто питон используется как средство для построения DSL, отсюда эти __getattr__, __getattribute__, и еще целая гора встроенных атрибутов, предназначенных для переопределения штатного поведения типов. И в итоге ты не можешь даже вывести тип банального сложения аргументов, поскольку __add__ может вернуть что угодно, пусть даже стандартные функции и пытаются возвращать целостно типы. Для решения этой проблемы создатели PyPy не угадывают типы, а тупо записывают типы, по факту полученные при исполнении на интерпретаторе, а для предсказуемости повторного вызова той же функции стандартная либа переписана так, что алгоритм принятия решений о восприятии типов и выдаче разных типов видим для оптимизитора, и таким образом оптимизатор может насквозь вывести тип, вплоть до схлопывания всей иерархии вызовов в одну функцию, хранящую промежуточные переменные в регистрах вместо абстрактного объекта в куче.

Это я как бы о чем... Питон весь построен на той или иной степени манкипача - в идеале бы его нужно преобразовать во что-то более адекватное. Вот тот же __getattribute__ в стандартных библиотеках аще не используется - слишком уж уродливый костыль. С другой стороны, с __getattr__ дела обстоят несколько сложнее, это довольно частый гость, и по сути это более тонкий вариант манкипача.

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

У меня глаза плачут кровавыми слезами, когда я вижу, как жаву пишут на питоне или JS. В итоге берется всё худшее от жавы и от питона/js в одном коде: ублюдочная модель наследования плюс жалкая пародия на типизацию и интерфейсы.

byko3y ★★★★
() автор топика
Ответ на: комментарий от cherry_boy

ожидаемому поведению

Опять же, кем ожидаемому? Почему чьи то ожидания должны как то на меня влиять?

eternal_sorrow ★★★★★
()
Ответ на: комментарий от byko3y

У меня глаза плачут кровавыми слезами, когда я вижу, как жаву пишут на питоне или JS. В итоге берется всё худшее от жавы и от питона/js в одном коде: ублюдочная модель наследования плюс жалкая пародия на типизацию и интерфейсы.

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

anonymous
()
Ответ на: vba от anonymous

ехал dim через redim!

Shadow ★★★★★
()
Ответ на: комментарий от cherry_boy

Ты упускаешь один момент - как в анекдоте - «я всегда о них думаю». «сильная половая конституция», например, от социума не зависит.

Shadow ★★★★★
()

Я подниму тему некоторыми своими конкретными идеями - заодно будет немного яснее, что же я тут у вас пытаюсь выколядовать. Меня не особо сильно волнует сверхпроизводительность кода на питоне - она должна быть просто неплохая, не в 1000 раз ниже сишной. Синтаксис желательно оставить прежним, потому что именно эта простота и является коньком, который, однако, не получается хорошо реализовать, из-за чего возникает столько реализаций: cpython, PyPy, Cython, Jython, IronPython, Python for .NET, Parakeet, Nuitka, Stackless, Unladen Swallow - половина из которых сдохла.
https://xkcd.com/927/

Начну с кода:

>>> a = ([42],)
>>> a[0] += [43, 44]
TypeError: 'tuple' object does not support item assignment
>>> a
([42, 43, 44],)
>>> a = ([42],)
>>> b = a[0]
>>> b += [43, 44]
>>> a
([42, 43, 44],)

>>> x = y = [1,2,3]
>>> x = x + [4]
>>> x == y
False
>>> x = y = [1,2,3]
>>> x += [4]
>>> x == y
True
>>> x = [[]]*5
>>> x
[[], [], [], [], []]
>>> x[0].append(0)
>>> x
[[0], [0], [0], [0], [0]]

Здесь мы приходим к некоему неожиданному выводу, на который особенно наводит ошибка «'tuple' object does not support item assignment»: синтаксис питона не поддерживает работу с изменяемыми данными. Синтаксис адаптирован к тому, что значение операции всегда создается заново, как это сделано с числами, строками, кортежами. По логике вещей, x[0].append(0) должно было бы создать новый или взять уникальный список из нулевого элемента и добавить в него нуль, но в CPython вместо этого неявно изменяется единственный экземпляр пустого списка, который хранится в нескольких местах. И если в трех строчках кода нам это очевидно, то в большом проекте можно очень долго вылавливать подобные проблемы.

Что же это за такой странный зверь тогда - списки [] питона? Это оптимизация кортежей, костыль, потому что операции с пересозданием кортежей на большом числе значений становятся очень медленными. К слову, создатель Clojure не согласился с таким подходом, и сделал быстрые неизменяемые списки с чем-то вроде partial-copy-on-write при выполнении операций над ними списками. Гвидо же сделал доживший до наших дней костыль, но не сделал адекватные средства работы с этими костылями.

Что делать с изменяемыми данными? К которым, к слову, также относятся и объекты в целом. Например, можно делать copy-on-write на присвоении, и явные операции изменения данных по месту без копирования: b.append.., b[].., b +=... Результат: устранение случайных связей между объектами, гарантия неизменяемости извне обладаемого объекта, а в итоге - упрощение параллелизации, оптимизации, тестирования. К сожалению, отваливается код, который опирался на старую, запутанную и неочевидную логику работы списков, когда список может неконтролировано меняться из неожиданных мест.

Почему Гвидо сразу не сделал язык таким? Потому что та реализация оригинального интерпретатора не давала простой возможности отслеживать ссылки и копировать объекты, в частности, это требовало как минимум введения двойного указателя (вложенного), где указатель из функции на Си читает адрес объекта (который может меняться), а уже по этому адресу лежат сами данные, уже скопированные или общие неизмененные.

Однако, я сам не могу придумать лаконичных и совместимых способов добавить четкое разграничение изменяемых и неизменяемых объектов в рамках имеющегося языка. Ваши предложения? Например, можно было бы сделать все объекты copy-on-write, а явные ссылки делать через "({'first': 1, 'second': 2},)", то есть, такой себе боксинг, где роль контейнера выполняет кортеж, который неизменяем, и потому никогда не будет копироваться, оставаясь единой ссылкой на объект «{'first': 1, 'second': 2}».

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

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Что делать с изменяемыми данными

Ничего не надо делать. Разве что во все туториалы «питон за 3 часа» в самое начало запихать дисклеймер, что деструктивные операции опасны и пользоваться ими без особой необходимости нельзя.

Ваши предложения

Добавить массивы как в пыхе, а всё остальное депрекейтнуть.

Почему Гвидо сразу не сделал язык таким

Потому что он плохо подумал. То что + копирует список, а += меняет по месту это как-то очень оригинально. Ну а * которая копирует ссылку вместо копирования списка это вообще эпик. И то, что так и осталось, говорит только что Гвидо конченый аутист — ему некая внутренняя красота была важнее, чем практическая ценность. В итоге получился язык, в котором каждая фича имеет свою внутреннюю красоту и логику, но всё вместе это выглядит как нагромождение кучи говна несвязанных между собой костылей.

То что ты пытаешься тут осмыслить — это как раз попытка придумать как поменять внутреннюю логику фич питона так, чтобы они вместе образовали что-то более вразумительное и цельное. Проблема в том, что фич нагорожено овердохрена, что неудивительно, ведь их не нужно было как-то друг с другом согласовывать и соотносить. Но ты хочешь именно такой согласованности. Предполагаю, что сделать это не получится, если не выкинуть 90% этих «фич ради фич», т.к. всегда где-то будут вылезать побочные эффекты о которых ты не подумал.

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

Потому что их объективно нет. Т.е. теоретически это может и возможно, но осмыслить это даже толпой людей, как некий декларативный набор изменений нельзя. Человеческой думки на это не хватит. Можно попытаться действовать итеративно, т.е. патчить какую-то фичу, смотреть как это работает в реальности, чтобы понять, какие проблемы всплыли, снова патчить эту фичу и т.д. Но на это уйдут годы, даже если всё питоносообщество будет этого хотеть, а оно не хочет и только радостно продолжает запиливать «прекрасные новые фичи».

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

даже если всё питоносообщество будет этого хотеть, а оно не хочет и только радостно продолжает запиливать «прекрасные новые фичи».

Вот-вот, этим сладкоежкам уже не помочь. Чем дальше в лес, тем труднее его починить. Уже все опустили руки, cpython это единственная живая реализация. В общем, пришли к консенсусу: питон не для продакшна. Как заменитель перла и псевдокода из учебников сгодится, но не более того.

anonymous
()
Ответ на: комментарий от no-such-file

Добавить массивы как в пыхе, а всё остальное депрекейтнуть.

Эм-м-м... а тебе не кажется, что массивы пыха - еще более топорные костыли, которые изначально вообще не предполагалось использовать в роли списков? К тому же, модель «общее изменяемое состояния» в целом создает проблемы в крупных проектах. Это ближе к массивам Си, в Lua сделано так же, потому все три эти языка (вместе с PHP) довольно шустро бегают - но погружение в низкоуровые конструкции не есть хорошо по отношению к питону.

Можно попытаться действовать итеративно, т.е. патчить какую-то фичу, смотреть как это работает в реальности, чтобы понять, какие проблемы всплыли, снова патчить эту фичу и т.д.

Я сомневаюсь, что так уж много софтописцев использует кривые функции списков. Наоборот, они, скорее всего, стараются развязывать ссылки на объекты, вроде new_list = list(old_list) - 600 вызовов функции list() присутствует в стандартной либе питона, пусть некоторые из них и нужны только для преобразования итератора в список.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

а тебе не кажется, что массивы пыха - еще более топорные костыли

Там же CoW, всё как ты хочешь.

не предполагалось использовать в роли списков

Возникает вопрос, а зачем вообще нужна «роль списков»? Массивы в пыхе отлично справляются с тем, что в питоне предполагается делать с помощью кортежей, списков и словарей вместе взятых. А всё потому, что в питоне списки ради списков, а не ради решения практических задач.

кривые функции списков

Чем же они кривые? В контексте списков они вполне логичны. Можно хоть на лекциях использовать как иллюстрацию устройства сферических списков в вакууме. С академической точки зрения всё замечательно.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

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

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

anonymous
()
Ответ на: комментарий от no-such-file

а тебе не кажется, что массивы пыха - еще более топорные костыли

Там же CoW, всё как ты хочешь.

Да, это правда, есть такое.

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

Можно выполнить кортежи, списки, и словари при помощи строки и строковых операций - как и сделано в Tcl. Но это не значит, что всепоглощающий подход удобен и эффективен. Можно же ведь засунуть в массив еще и функции, и потом отлавливать места конфликтов идентификаторов. Конкретно в случае с PHP проблемы имеются, например, при слиянии двух ассоциативных массивов, в которых есть численные ключи - вот тебе разные функции для массива и ассоциативного массива перекрыли друг друга, и привет.

К слову, в питоне кортеж и список - это одна и та же структура, просто кортеж неизменяем. В каком-то смысле объект в PHP - это массив без copy-on-write.

Возникает вопрос, а зачем вообще нужна «роль списков»?

Очень хороший вопрос. Не только лишь все понимают: списки нужны для описания намерения погромиста иметь последовательный набор объектов в одном хранилище. Его даже не волнует механизм реализации списков - ему тупо нужен интерфейс последовательного хранения, последовательной выборки, присоединения списков друг к другу для получения такого же хранилища в результате, удаления элементов с сохранением последовательности. В этом хранилище могут быть механизмы хранения ключ-значение, но они не должны мешать программисту пользоваться тем, что он ждет - последовательным списком элементов.

Чем же они кривые? В контексте списков они вполне логичны. Можно хоть на лекциях использовать как иллюстрацию устройства сферических списков в вакууме. С академической точки зрения всё замечательно.

Вот это норм, по-твоему?

>>> x = [[]]*5
>>> x
[[], [], [], [], []]
>>> x[0].append(0)
>>> x
[[0], [0], [0], [0], [0]]

byko3y ★★★★
() автор топика
Ответ на: комментарий от anonymous

типа запрета в жс обходить списки штатным for in

Во-первых не for in, а for of, а во-вторых нет никакой проблемы.

> let a=[1,2,3]
> a
[ 1, 2, 3 ]
> a['x']=4
4
> a
[ 1, 2, 3, x: 4 ]
> for(let e of a) console.log(e)
1
2
3
no-such-file ★★★★★
()
Ответ на: комментарий от byko3y

как и сделано в Tcl

Зачем ты съезжаешь на tcl, если я тебе его не предлагал? В пыхе сделано эффективно. Даже эффективнее чем в красивом питоне без «всепоглощающего подхода».

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

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

Вот это норм, по-твоему?

А что тут такого? Списки передаются по ссылке? Да. Ну вот и получи 5 копий ссылки. Всё логично. И вот это и есть настоящий python way - допускать любую дичь, если она оправдана какой-то внутренней логикой. А то что в таком виде оно нафиг не упало - ну это так само же получилось, из логики реализации, а значит это правильно и канонично.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Во-первых не for in, а for of, а во-вторых нет никакой проблемы.

Напоминаю, что for...of - это конструкция из ES6.

> a
[ 1, 2, 3, x: 4 ]
> for (let val in a) console.log(val)
0
1
2
x

byko3y ★★★★
() автор топика
Ответ на: комментарий от no-such-file

В пыхе сделано эффективно. Даже эффективнее чем в красивом питоне без «всепоглощающего подхода».

Если не считать горы функций array_*, которые предлагаю широкий выбор костылей для адаптации единого хранилища к форматам хранения. CoW - годнота, ни секунды не спорю.

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

$array = array("0" => "first",  
              "foo" => "bar", 5);
$array2 = array("0" => "second",  
              "foo" => "bar", 5);
              
$merged = array_merge($array, $array2);
$added = $array + $array2;
              
echo "merged:\n";
foreach( $merged as $key => $value ){
    echo $key."\t=>\t".$value."\n";
}
echo "----------------------------\n";
echo "added:\n";
foreach( $added as $key => $value ){
    echo $key."\t=>\t".$value."\n";
}
merged:
0	=>	first
foo	=>	bar
1	=>	5
2	=>	second
3	=>	5
----------------------------
added:
0	=>	first
foo	=>	bar
1	=>	5

Просто ссу кипятком от удобство и понятности операций.

byko3y ★★★★
() автор топика
Ответ на: комментарий от no-such-file

нет никакой проблемы

Да уж, всего-то набили гору шишек и через 20 лет сделали наконец костыль для «массивов».

anonymous
()
Ответ на: комментарий от byko3y

это конструкция из ES6

for (let val in a), а что let не из ES6? for/in из ES3, который уже давно протух и не используется. Т.е. в ЖС как раз сделали то, о чём ты тут мечтаешь.

no-such-file ★★★★★
()
Ответ на: комментарий от anonymous

через 20 лет

Через 10. forEach появился ещё в es5 в 2009. Ну замечательно, что осознали, пилят язык в нужном направлении. И в пыхе такая же ситуация. Только в питоне уже 30 лет накидывают новые горы говна, попытка как-то изменить ситуацию с python3 откровенно провалилась. Именно потому провалилась, что Гвидо не осознал главной проблемы и просто перетасовал фичи, чуток изменив совсем уж кривые вещи в которые его тыкали носом. Питон 3 не стал «лучшим питоном» а просто «другим питоном вид сбоку». Естественно народ недоумевает, нахрена он сдался.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Точнее, for of это реплика питоновского for. То есть не то чтобы костыль, а так оно сразу должно быть сделано как сахар над итераторами. Ну и в js потом докинули специализированные коллекцие: List, Map. Видать не так прикольно всё делать через Object.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.