Еще раз. Python никогда не создавался как язык для обучения. Тот факт, что Python испытал влияние ABC, никоим образом не означает, что сам Python предназначен для тех же целей. У вас ошибка в логике.
Кортеж поддерживает иммутабельность ссылок, а не значений. Это сильно облегченная версия массива для хранения и передачи последовательности элементов, а вовсе не наоборот, как ошибочно написано в статье.
По хорошему, нужно было либо запрещать хранить в кортеже изменяемые значения, либо делать копии.
Зачем? Если вам нужны иммутабельные элементы в контейнере, используйте для этого иммутабельные значения. Просто ((1, 2), 1), никаких проблем. Не думайте, что иммутабельность в Python должна быть эквивалентом константности из языка С.
Потому что присваивание элемента запрещено для иммутабельного tuple. Выражение x[0] += 1 не может создать новый x[0], поскольку такое выражение делает следующее:
i = x[0]
i += 1
x[0] = i
Операция x[0] = iне поддерживается tuple. Он никогда не меняет свои ссылки.
Честно говоря, мне сложно с вами спорить из-за сильной расплывчатости формулировок и пространных рассуждений. Какое нарушение? Какого алгоритма? Что?
Да, типы, методы и функции из расширений тоже являются built-in, и нет, определенно не нужно менять смысл выражений (...), [...] и {...} в Python. Все, пощадите мой мозг)
Но работает x += (1, ). Что есть нецелостность языка.
Ларчик открывается просто.
>>> x = ()
>>> id(x)
140362334412872
>>> x += (1,)
>>> id(x)
140362217698360
Для иммутабельного tuple выражение x += (1,) эквивалентно x = x + (1,). Присваивается новое значение. Так работают все иммутабельные типы в Python. Мутабельные меняются "по месту".
Pickle же ж. Схоронили один класс, а достали уже в другой. Изменяемые определения классов — это почти всегда зло. Они не зло только при написании и отладке. Конкретно в случае параллельного выполнения задач изменяемые определения классов становятся злом в квадрате.
Cпойлер
Что не помешало Go быть статически типизированным и статически компилированным.
Почему Python должен быть статически типизированным и статически компилируемым?
Много чего в CPython нельзя изменить во время выполнения: огромные слои стаднартной реализации неподвластны динамичности, я упомянул лишь один пример в статье — невозможность переопределять стандартные списки.
Встроенные типы являются исключением. Они не подлежат изменению по соображениям производительности, но можно унаследоваться от встроенного типа и переопределить или дополнить его поведение, а из-за утиной типизации в общем случае нет нужды ожидать именно list или dict — достаточно объекта, который реализует набор методов.
Потенциальная возможность динамического изменения класса при выполнении и возможность изменять доступ к атрибутам во время выполнения сами по себе закрывают целый пласт возможностей параллелизации и оптимизации, поскольку в общем случае нужно всегда держать наготове второй интерператор, а для частного случая можно просто написать расширение на Си.
Такая гибкость является намеренной фишкой Python, которая отличает его от других языков.
with — не понимаю претензии, где тут goto? Вызов функции, как и вызов вложенного блока в нотации with, не нарушает структурированности кода.
Там же, где try/except/finally, только под другим соусом. Не нарушает структурированности кода сам по себе, точно так же как его не нарушают yield/await, которые выполняются строго последовательно в пределах сопрограммы. При await планировщик может передать управление другой сопрограмме, но этот процесс скрыт от программиста, и вам не нужно следить за этим. Вы же не нарекаете на то, что вытесняющая многозадачность средствами ОС нарушает структурированность исходного кода?)
Если придираться к деталям, то генераторы — это самые что ни на есть зеленые потоки, а вызов next/yield переключает контекст. Это не вызов сопрограммы, потому что точка входа неопределена — вызывающая функция не знает, что вызывает.
Генераторы и корутины являются сопрограммами. Я не представляю, откуда вы берете все эти идеи.
Ссылки на массивы формируют неявное поведение, которое непрактично. Я соглашусь разве что с тем, что нельзя менять поведение для старого кода — новые списки должны быть явно обозначены. Здесь фундаментальная проблема заключается даже не в списках, а в отсутствии явного разграничения значений и ссылок на значения.
В питоне все значения имеют ссылочный характер. Любая переменная является ссылкой на значение (указателем/ссылкой в терминах C/C++), передача по значению отсутствует. Однако существуют неизменяемые объекты (int, float, tuple, str, frozenset etc), когда при модификации с ссылкой связывается новое вычисленное значение вместо модификации "по месту". Именно поэтому x[0] += 1 с tuple не работает.
не дают модульно тестировать. Правильно отработавший в тесте кусок кода может выдать ошибку при работе целой системы, и никак вы от этого не защититесь в рамках CPython;
Это проблема модульного тестирования, которая решается интеграционным тестированием системы в целом. Причем тут питон?
создают большие сложности оптимизации. Объявление класса не дает вам гарантии по поводу фактической работы класса. По этой причине единственный успешный проект оптимизатора, PyPy, использует трассировку для обнаружения фактической последовательности выполняемых действий методом пробы;
Это следствие динамизма и утиной типизации, основных фич питона. Разумеется, что класс (как и почти любая вещь в питоне) может быть изменен во время выполнения. Даже байкод.
не состыковываются с параллельным выполнением кода. Например, тот же multiprocessing работает с копиями определений классов, и если вы не дай бог измените описание классов в одной из копий, то ваше приложение рискует развалиться.
Потому что multiprocessing работает с разными процессами, у которых внезапно разные адресные пространства. Причем тут питон?
Более тонкий вариант динамических классов — это переопределение доступа к атрибутам через getattribute, getattr и прочие. Зачастую они используются в качестве обычных геттеров-сеттеров, для делегации функций объекту-полю, и изредка — для организации DSL.
И что из этого следует? Эти магические методы обычно используются в библиотеках, фреймворках, и там, где необходимо переопредлить логику поиска атрибутов. В обычном коде встречается редко.
Горячая замена классов нужна для целей отладки и банальной кодописи, но это все-таки должен быть специализированный инструмент для разработчика, а не артефакт во время выполнения, от которого нельзя избавиться.
(См. выше) К слову, почему "это все-таки должен быть специализированный инструмент"? Что подразумевается под этим? Он должен быть статическим?
Это прямо-таки запущенный случай GoTo, когда выполнение не просто бесконтрольно прыгает по коду — оно прыгает по стэкам.
Я не понимаю каким образом сопрограммы и корутины являются запущенным случаем goto. Исключения, continue, break, with, return тоже можно рассматривать как частный случай goto.
Адрес почты регистрозависим! По крайней мере до знака @.
Строго говоря, строка ДО знака @ НЕ является регистрозависимой или регистронезависимой. Это определено реализацией сервера. Строка ПОСЛЕ @ адресует сервер, и она является регистроНЕзависимой. Извините за мой французский.
Так делают. Elasticsearch передает запросы в теле методом GET, и он так же позволяет производить поиск методом POST. Его поисковые запросы могут быть внушительными)
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request. https://tools.ietf.org/html/rfc7231#section-4.3.1
Еще раз. Python никогда не создавался как язык для обучения. Тот факт, что Python испытал влияние ABC, никоим образом не означает, что сам Python предназначен для тех же целей. У вас ошибка в логике.
Python никогда не создавался как язык для обучения, ты перепутал его с BASIC.
https://www.artima.com/intv/python.html
Лучше просто сошлитесь на что-нибудь.
Ага, а никто и не в курсе. RTTI является тоже чем-то из области абсурда)
Python имеет сильную динамическую типизацию.
Фактически, любой код на CPython дергает вызовы С API и системные вызовы ОС.
Кортеж поддерживает иммутабельность ссылок, а не значений. Это сильно облегченная версия массива для хранения и передачи последовательности элементов, а вовсе не наоборот, как ошибочно написано в статье.
Зачем? Если вам нужны иммутабельные элементы в контейнере, используйте для этого иммутабельные значения. Просто
((1, 2), 1), никаких проблем. Не думайте, что иммутабельность в Python должна быть эквивалентом константности из языка С.Мы с вами сейчас по второму кругу пойдем
Да.
Потому что присваивание элемента запрещено для иммутабельного tuple. Выражение
x[0] += 1не может создать новыйx[0], поскольку такое выражение делает следующее:Операция
x[0] = iне поддерживается tuple. Он никогда не меняет свои ссылки.Честно говоря, мне сложно с вами спорить из-за сильной расплывчатости формулировок и пространных рассуждений. Какое нарушение? Какого алгоритма? Что?
Да, типы, методы и функции из расширений тоже являются built-in, и нет, определенно не нужно менять смысл выражений (...), [...] и {...} в Python. Все, пощадите мой мозг)
Ларчик открывается просто.
Для иммутабельного tuple выражение
x += (1,)эквивалентноx = x + (1,). Присваивается новое значение. Так работают все иммутабельные типы в Python. Мутабельные меняются "по месту".Почему Python должен быть статически типизированным и статически компилируемым?
Встроенные типы являются исключением. Они не подлежат изменению по соображениям производительности, но можно унаследоваться от встроенного типа и переопределить или дополнить его поведение, а из-за утиной типизации в общем случае нет нужды ожидать именно list или dict — достаточно объекта, который реализует набор методов.
Такая гибкость является намеренной фишкой Python, которая отличает его от других языков.
Там же, где try/except/finally, только под другим соусом. Не нарушает структурированности кода сам по себе, точно так же как его не нарушают yield/await, которые выполняются строго последовательно в пределах сопрограммы. При await планировщик может передать управление другой сопрограмме, но этот процесс скрыт от программиста, и вам не нужно следить за этим. Вы же не нарекаете на то, что вытесняющая многозадачность средствами ОС нарушает структурированность исходного кода?)
Генераторы и корутины являются сопрограммами. Я не представляю, откуда вы берете все эти идеи.
Попробуй сделать
int.__hash__()вместо hash(int) и многое прояснится само собой.https://docs.python.org/3/reference/datamodel.html#special-method-lookup
В питоне все значения имеют ссылочный характер. Любая переменная является ссылкой на значение (указателем/ссылкой в терминах C/C++), передача по значению отсутствует. Однако существуют неизменяемые объекты (int, float, tuple, str, frozenset etc), когда при модификации с ссылкой связывается новое вычисленное значение вместо модификации "по месту". Именно поэтому x[0] += 1 с tuple не работает.
https://ru.wikipedia.org/wiki/Стратегия_вычисления#Вызов_посоиспользованию(call_by_sharing)
Это проблема модульного тестирования, которая решается интеграционным тестированием системы в целом. Причем тут питон?
Это следствие динамизма и утиной типизации, основных фич питона. Разумеется, что класс (как и почти любая вещь в питоне) может быть изменен во время выполнения. Даже байкод.
Потому что multiprocessing работает с разными процессами, у которых внезапно разные адресные пространства. Причем тут питон?
И что из этого следует? Эти магические методы обычно используются в библиотеках, фреймворках, и там, где необходимо переопредлить логику поиска атрибутов. В обычном коде встречается редко.
(См. выше) К слову, почему "это все-таки должен быть специализированный инструмент"? Что подразумевается под этим? Он должен быть статическим?
Я не понимаю каким образом сопрограммы и корутины являются запущенным случаем goto. Исключения, continue, break, with, return тоже можно рассматривать как частный случай goto.
Вы описали так называемый type punning, который может быть использован для реализации рудиментарного полморфизма, но сам по себе им не является.
В статье много рациональных зёрен, но они размазаны по стене текста с неясными претензиями.
Строго говоря, строка ДО знака @ НЕ является регистрозависимой или регистронезависимой. Это определено реализацией сервера. Строка ПОСЛЕ @ адресует сервер, и она является регистроНЕзависимой. Извините за мой французский.
Нет. Локальная часть до @ интерпретируется сервером. Домен к регистру не чувствителен.
https://tools.ietf.org/html/rfc5321#section-2.3.11
Зачёт-то поставили?
Так делают. Elasticsearch передает запросы в теле методом GET, и он так же позволяет производить поиск методом POST. Его поисковые запросы могут быть внушительными)
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html
https://developer.twitter.com/en/docs/api-reference-index.html