#astronomy #dangers
«DART дал нам представление о сложной гравитационной физике, которую невозможно изучить в лаборатории, и все эти исследования помогают нам узнать больше для защиты Земли в случае возникновения реальной угрозы. Существует ненулевая вероятность того, что астероид или комета приблизится и подвергнет планету опасности. Теперь у нас есть дополнительная линия защиты от такого рода внешних угроз», — считает Ричардсон.
https://3dnews.ru/1109977/missiya-nasa-dart-pomogla-uchyonim-uznat-bolshe-o-geofizike-legashchey-v-osnove-formirovaniya-i-evolyutsii-asteroidov
«DART дал нам представление о сложной гравитационной физике, которую невозможно изучить в лаборатории, и все эти исследования помогают нам узнать больше для защиты Земли в случае возникновения реальной угрозы. Существует ненулевая вероятность того, что астероид или комета приблизится и подвергнет планету опасности. Теперь у нас есть дополнительная линия защиты от такого рода внешних угроз», — считает Ричардсон.
https://3dnews.ru/1109977/missiya-nasa-dart-pomogla-uchyonim-uznat-bolshe-o-geofizike-legashchey-v-osnove-formirovaniya-i-evolyutsii-asteroidov
3DNews - Daily Digital Digest
Миссия NASA DART помогла узнать больше о геофизике, лежащей в основе формирования и эволюции астероидов
В 2022 году Национальное управление по аэронавтике и исследованию космического пространства (NASA) США провело миссию Double Asteroid Redirection Test (DART), в рамках которой космический аппарат столкнули с астероидом Диморф (Dimorphos). Цель миссии заключалась…
#abtesting #bayesian
"Good decisions for business are more important than being on the safe side."
https://youtu.be/8huhVCMmS_c?si=ypw66iyvoBL3Jidr
"Good decisions for business are more important than being on the safe side."
https://youtu.be/8huhVCMmS_c?si=ypw66iyvoBL3Jidr
YouTube
Ruben Mak | Successfully applying Bayesian statistics to A/B testing in your business
PyData Amsterdam 2017
A lot of theory is available on how the statistics of A/B testing could be improved using Bayesian statistics. In this talk I will discuss several theoretical problems and I will share my experiences on whether they actually impact…
A lot of theory is available on how the statistics of A/B testing could be improved using Bayesian statistics. In this talk I will discuss several theoretical problems and I will share my experiences on whether they actually impact…
#python #vb #with #contextmanagers
"Не исключено, что контекстные менеджеры окажутся почти такими же важными, как сами подпрограммы. Мы затронули лишь самую верхушку айсберга […].
В языке Basic есть предложение with, как и во многих других языках. Но все они делают совсем не то – они лишь экономят время на повторяющемся поиске атрибутов с точкой, не производя ни инициализации, ни очистки. Не нужно думать, что раз названия одинаковы, то одинаковы и функции. Предложение with – очень мощная штука.
– Рэймонд Хэттингер"
Капец. Так вот откуда Рэй взял идею конструкций with. А какого хрена тогда было не сделать так же, как в Visual Basic, вложенные with с сокращённой нотацией?! Это ж очень удобно. Для доступа к полю A.B.C в VB можно написать
Кстати, до сих пор не пойму, почему в Python переменная, объявленная в контекстном менеджере, доступна ПОСЛЕ выхода из контекста. Это выглядит крайне нелогично:
"Не исключено, что контекстные менеджеры окажутся почти такими же важными, как сами подпрограммы. Мы затронули лишь самую верхушку айсберга […].
В языке Basic есть предложение with, как и во многих других языках. Но все они делают совсем не то – они лишь экономят время на повторяющемся поиске атрибутов с точкой, не производя ни инициализации, ни очистки. Не нужно думать, что раз названия одинаковы, то одинаковы и функции. Предложение with – очень мощная штука.
– Рэймонд Хэттингер"
Капец. Так вот откуда Рэй взял идею конструкций with. А какого хрена тогда было не сделать так же, как в Visual Basic, вложенные with с сокращённой нотацией?! Это ж очень удобно. Для доступа к полю A.B.C в VB можно написать
with A.B
.C=...
Кстати, до сих пор не пойму, почему в Python переменная, объявленная в контекстном менеджере, доступна ПОСЛЕ выхода из контекста. Это выглядит крайне нелогично:
import pymc as pm
# Define a model using a context manager
with pm.Model() as model:
# Define random variables within the model
mu = pm.Normal('mu', mu=0, sigma=1)
sigma = pm.HalfNormal('sigma', sigma=1)
observed_data = pm.Normal('observed_data', mu=mu, sigma=sigma, observed=[1.2, 1.8, 2.4])
# Outside the context, you can still access the 'model' and the variables
model.do_something()
❤1
#law #security
"Было установлено, что Uber нарушала Общий регламент ЕС по защите персональных данных (GDPR), передавая и храня информацию о европейских таксистах на серверах в США в течение более двух лет. Речь идёт о разнообразной конфиденциальной информации, включая учётные записи водителей Uber, лицензии на работу в такси, данные о местоположении, фотографии, платёжные реквизиты, удостоверяющие личность документы и др.
DPA уже дважды штрафовала Uber. Первый штраф в размере €600 тыс. был наложен в 2018 году после того, как компания не сообщила об утечке данных, произошедшей двумя годами ранее. В 2023 году Uber была оштрафована на €10 млн за неполную детализацию периодов хранения данных о европейских таксистах. Нынешний штраф стал самым крупным, но Uber собирается его обжаловать."
Закон о хранении данных на серверах определённой страны, если честно, тупейший, и нарушает права людей. На мой взгляд, он не связан с безопасностью клиентских данных НИКАК. От того, расположен сервер в Брюсселе или Атланте, его безопасность не зависит (при условии нахождений в дата-центре с нужным сертификатом защиты). Единственное желание, которое прослеживается - это желание правительств иметь доступ ко всем данным своих граждан. А я ХОЧУ хранить свои личные данные в любой стране, где мне надо, и подите все нахер со своими указаниями, где можно хранить мои данные.
https://3dnews.ru/1110020/uber-oshtrafovali-v-niderlandah-na-290-mln-za-nebezopasnuyu-peredachu-dannih
"Было установлено, что Uber нарушала Общий регламент ЕС по защите персональных данных (GDPR), передавая и храня информацию о европейских таксистах на серверах в США в течение более двух лет. Речь идёт о разнообразной конфиденциальной информации, включая учётные записи водителей Uber, лицензии на работу в такси, данные о местоположении, фотографии, платёжные реквизиты, удостоверяющие личность документы и др.
DPA уже дважды штрафовала Uber. Первый штраф в размере €600 тыс. был наложен в 2018 году после того, как компания не сообщила об утечке данных, произошедшей двумя годами ранее. В 2023 году Uber была оштрафована на €10 млн за неполную детализацию периодов хранения данных о европейских таксистах. Нынешний штраф стал самым крупным, но Uber собирается его обжаловать."
Закон о хранении данных на серверах определённой страны, если честно, тупейший, и нарушает права людей. На мой взгляд, он не связан с безопасностью клиентских данных НИКАК. От того, расположен сервер в Брюсселе или Атланте, его безопасность не зависит (при условии нахождений в дата-центре с нужным сертификатом защиты). Единственное желание, которое прослеживается - это желание правительств иметь доступ ко всем данным своих граждан. А я ХОЧУ хранить свои личные данные в любой стране, где мне надо, и подите все нахер со своими указаниями, где можно хранить мои данные.
https://3dnews.ru/1110020/uber-oshtrafovali-v-niderlandah-na-290-mln-za-nebezopasnuyu-peredachu-dannih
3DNews - Daily Digital Digest
Uber оштрафовали в Нидерландах на €290 млн за хранение данных водителей в США
Американскую компанию Uber Technologies оштрафовали на €290 млн в Нидерландах.
#hardware #storage
"На территории Таиланда у американской компании Western Digital функционирует предприятие, отвечающее за выпуск 80 % всех жёстких дисков в мире. Компания собирается увеличить его штат почти в полтора раза и вложить в расширение производства $693 млн, данная инициатива уже получила поддержку со стороны местных властей.
За десятилетие власти Таиланда в общей сложности одобрили инвестиции на развитие в стране производства жёстких дисков на сумму $2,43 млрд. В прошлом году разрешение вложить $470 млн на расширение своих производственных мощностей в стране получила американская компания Seagate Technology. Всего по итогам текущего года в различные сферы экономики Таиланда было вложено около $23,5 млрд."
А в России что? Климат не тот, видать.
https://3dnews.ru/1109993/vlasti-tailanda-odobrili-investitsii-western-digital-v-summe-693-mln-napravlyaemie-na-rasshirenie-proizvodstva-gyostkih-diskov
"На территории Таиланда у американской компании Western Digital функционирует предприятие, отвечающее за выпуск 80 % всех жёстких дисков в мире. Компания собирается увеличить его штат почти в полтора раза и вложить в расширение производства $693 млн, данная инициатива уже получила поддержку со стороны местных властей.
За десятилетие власти Таиланда в общей сложности одобрили инвестиции на развитие в стране производства жёстких дисков на сумму $2,43 млрд. В прошлом году разрешение вложить $470 млн на расширение своих производственных мощностей в стране получила американская компания Seagate Technology. Всего по итогам текущего года в различные сферы экономики Таиланда было вложено около $23,5 млрд."
А в России что? Климат не тот, видать.
https://3dnews.ru/1109993/vlasti-tailanda-odobrili-investitsii-western-digital-v-summe-693-mln-napravlyaemie-na-rasshirenie-proizvodstva-gyostkih-diskov
3DNews - Daily Digital Digest
Western Digital вложит $693 млн в расширение производства жёстких дисков в Таиланде
На территории Таиланда у американской компании Western Digital функционирует предприятие, отвечающее за выпуск 80 % всех жёстких дисков в мире.
Forwarded from kyrillic
Новая программа для 🇪🇸 испанских номадов от Эстремадуры (региона на границе с Португалией): можно получить до 15к евро за переезд в маленький город региона.
Условия простые: испанский номад-внж и переезд в город региона. Если до 30 лет и в городе до 5 тыс населения, то дают 10к сразу и 5к через два года. Для остальных 8к сразу и 4к через два года (новость, источник).
Подавать можно будет после того, как программу опубликуют в официальном вестнике Эстремадуры через три недели.
Мне кажется, что для тех, кому нужно экстремально экономить - интересный вариант: жить в Эстремадуре и так очень дешево (тем более в маленьком городке), а еще бонус дают. Уж точно лучше, чем во многих эмигрантских лимбах (пост).
Полагаю, что стоимость аренды дома/квартиры будет 400-600 евро/мес. На idealista есть и за 300 приличное.
Регион на границе с Португалией - всегда можно разнообразить жизнь поездкой к соседям. Жаль до моря неблизко!
Я бывал в регионе проездом, но никакого мнения не сложилось - вроде обычная приятная провинциальная Испания. Может кто-то из вас там живет или жил? Расскажите!
@kyrillic
Условия простые: испанский номад-внж и переезд в город региона. Если до 30 лет и в городе до 5 тыс населения, то дают 10к сразу и 5к через два года. Для остальных 8к сразу и 4к через два года (новость, источник).
Подавать можно будет после того, как программу опубликуют в официальном вестнике Эстремадуры через три недели.
Мне кажется, что для тех, кому нужно экстремально экономить - интересный вариант: жить в Эстремадуре и так очень дешево (тем более в маленьком городке), а еще бонус дают. Уж точно лучше, чем во многих эмигрантских лимбах (пост).
Полагаю, что стоимость аренды дома/квартиры будет 400-600 евро/мес. На idealista есть и за 300 приличное.
Регион на границе с Португалией - всегда можно разнообразить жизнь поездкой к соседям. Жаль до моря неблизко!
Я бывал в регионе проездом, но никакого мнения не сложилось - вроде обычная приятная провинциальная Испания. Может кто-то из вас там живет или жил? Расскажите!
@kyrillic
Forwarded from kyrillic
⚡️ Быстрая диванная аналитика по обвинениям в отношении Телеграма:
1️⃣ Вменяют по всему сразу, о чем писал в посте - и все виды нелегальный контента, и отмывание денег. Но самое главное - по новой во французском кодексе статье про администрированию ресурсов, которые распространяют плохое. Кажется, что по ней доказать легче всего.
2️⃣ Телеграм теперь официально маргинальная площадка в ЕС. Если в медиа будет раскручиваться этот нарратив (не очень вероятно, но все же), то будут и ограничения всего телеграма в каком-то виде (думаю, что удаление из сторов).
3️⃣ Получение гражданства - это не только права, но и обязанности. Французы могут спокойно судить своего гражданина за преступления в других странах. Про такие риски получения паспорта не говорят, хотя эти строки прочитает множество репатриантов, которым формально запрещено въезжать например в Малайзию.
4️⃣ Ограничения телеграма, точечные по чернухе или глобальные, будут вводиться небыстро, отток из-за них будет медленный. Но начнется процесс и с другой стороны - те, кто рулит нелегальным, станут осторожнее использовать тг, а значит и желающих распространять нелегальное через тг будет меньше.
Очевидно, что и любые монеты, связанные с телеграмом тоже будут использовать меньше, доверия к ним будет меньше.
5️⃣ Если у вас есть средства в официальном кошельке wallet, то я бы их вывел на всякий случай. Там уже висит плашка, что транзакции обрабатываются с задержкой (как подсказывают в комментах - из-за листинга dogs). Ну и самым рисковым можно поиграть в ton, самое время!
@kyrillic
1️⃣ Вменяют по всему сразу, о чем писал в посте - и все виды нелегальный контента, и отмывание денег. Но самое главное - по новой во французском кодексе статье про администрированию ресурсов, которые распространяют плохое. Кажется, что по ней доказать легче всего.
2️⃣ Телеграм теперь официально маргинальная площадка в ЕС. Если в медиа будет раскручиваться этот нарратив (не очень вероятно, но все же), то будут и ограничения всего телеграма в каком-то виде (думаю, что удаление из сторов).
3️⃣ Получение гражданства - это не только права, но и обязанности. Французы могут спокойно судить своего гражданина за преступления в других странах. Про такие риски получения паспорта не говорят, хотя эти строки прочитает множество репатриантов, которым формально запрещено въезжать например в Малайзию.
4️⃣ Ограничения телеграма, точечные по чернухе или глобальные, будут вводиться небыстро, отток из-за них будет медленный. Но начнется процесс и с другой стороны - те, кто рулит нелегальным, станут осторожнее использовать тг, а значит и желающих распространять нелегальное через тг будет меньше.
Очевидно, что и любые монеты, связанные с телеграмом тоже будут использовать меньше, доверия к ним будет меньше.
5️⃣ Если у вас есть средства в официальном кошельке wallet, то я бы их вывел на всякий случай. Там уже висит плашка, что транзакции обрабатываются с задержкой (как подсказывают в комментах - из-за листинга dogs). Ну и самым рисковым можно поиграть в ton, самое время!
@kyrillic
❤🔥1⚡1✍1
#sklearn #mlgems
У Винсента всегда классные выступления. Кратко рассматривает кэширование конвейера (Pipeline(...,memory=...)), роутинг весов, дообучение для потоковых данных (partial_fit), модуль semi_supervised, Но вы этот раз всё очень кратко и галопом по Европам.
https://www.youtube.com/watch?v=es_8_iT-oQk
У Винсента всегда классные выступления. Кратко рассматривает кэширование конвейера (Pipeline(...,memory=...)), роутинг весов, дообучение для потоковых данных (partial_fit), модуль semi_supervised, Но вы этот раз всё очень кратко и галопом по Европам.
https://www.youtube.com/watch?v=es_8_iT-oQk
YouTube
Vincent D. Warmerdam - Scikit-Learn can do THAT?!
Many of us know scikit-learn for it's ability to construct pipelines that can do .fit().predict(). It's an amazing feature for sure. But once you dive into the codebase ... you realise that there is just so much more.
This talk will be an attempt at demonstrating…
This talk will be an attempt at demonstrating…
#python #books
С трудом дочитал "Л. Рамальо. Python – к вершинам мастерства: Лаконичное и эффективное программирование" (в оригинале - Fluent Python, 2nd Edition).
Книгу скорее не рекомендую. Под 900 страниц, но затронутые темы требуют кратно большего количества материала и примеров.
Мало ценных для бизнеса примеров, в основном какие-то дурацкие. Странная подача материала - при обсуждении продвинутых концепций вроде метаклассов автор в каждой такой главе умоляет не использовать их, обходясь более простыми (и ограниченными) средствами, вместо того чтобы привести конкретные примеры, где применение продвинутых техник наиболее полезно.
Странная смесь подачи базовых концепций и обсуждения сложного материала, уходящего к корням, в реализацию на С, порой в другие языки. Много откровенно дебильных сносок (не используйте сноски, шутки и благодарности при написании книги).
Русский перевод не рекомендую точно.
Мудила-переводчик перевел на русский абсолютно все термины, к примеру, framework у него не фреймфорк, а каркас. Ты, сука, где слышал, чтобы русскоязычные программисты говорили - я, мол, каркас новый написал давеча...
При этом для зачастую сложных терминов, переведённых им по наитию, он постеснялся указать общепринятые англоязычные эквиваленты. А нахера, ведь его читатель, наверное, никогда не полезет в документацию, не появится на международных форумах, зачем упрощать ему жизнь?
Причем переводил, похоже, Промптом из 2000-х (привет многократноядерным машинам), слово в слово, из-за чего сложилось впечатление, что автор оригинальной книги - косноязычный идиот (так всегда бывает, когда плохой переводчик и редактор). Ощущение, что ни переводчик, ни редактор не являются программистами. Вы зачем тогда взяли эту работу? Через текст приходиться буквально продираться.
Тем не менее, я повыписывал вещи, которые не знал/забыл/показались достойными повторения. Изложу их в нескольких постах ниже.
С трудом дочитал "Л. Рамальо. Python – к вершинам мастерства: Лаконичное и эффективное программирование" (в оригинале - Fluent Python, 2nd Edition).
Книгу скорее не рекомендую. Под 900 страниц, но затронутые темы требуют кратно большего количества материала и примеров.
Мало ценных для бизнеса примеров, в основном какие-то дурацкие. Странная подача материала - при обсуждении продвинутых концепций вроде метаклассов автор в каждой такой главе умоляет не использовать их, обходясь более простыми (и ограниченными) средствами, вместо того чтобы привести конкретные примеры, где применение продвинутых техник наиболее полезно.
Странная смесь подачи базовых концепций и обсуждения сложного материала, уходящего к корням, в реализацию на С, порой в другие языки. Много откровенно дебильных сносок (не используйте сноски, шутки и благодарности при написании книги).
Русский перевод не рекомендую точно.
Мудила-переводчик перевел на русский абсолютно все термины, к примеру, framework у него не фреймфорк, а каркас. Ты, сука, где слышал, чтобы русскоязычные программисты говорили - я, мол, каркас новый написал давеча...
При этом для зачастую сложных терминов, переведённых им по наитию, он постеснялся указать общепринятые англоязычные эквиваленты. А нахера, ведь его читатель, наверное, никогда не полезет в документацию, не появится на международных форумах, зачем упрощать ему жизнь?
Причем переводил, похоже, Промптом из 2000-х (привет многократноядерным машинам), слово в слово, из-за чего сложилось впечатление, что автор оригинальной книги - косноязычный идиот (так всегда бывает, когда плохой переводчик и редактор). Ощущение, что ни переводчик, ни редактор не являются программистами. Вы зачем тогда взяли эту работу? Через текст приходиться буквально продираться.
Тем не менее, я повыписывал вещи, которые не знал/забыл/показались достойными повторения. Изложу их в нескольких постах ниже.
👍1
#python #codegems
По умолчанию любой экземпляр пользовательского класса считается истинным, но положение меняется, если реализован хотя бы один из методов bool или len. Функция bool(x), по существу, вызывает x.bool() и использует полученный результат. Если метод bool не реализован, то Python пытается вызвать x.len() и при получении нуля функция bool возвращает False. В противном случае bool возвращает True.
В программе на Python переход на другую строку внутри пар скобок [], {} и () игнорируется. Поэтому при построении многострочных списков, списковых включений, генераторных выражений, словарей и прочего можно обходиться без косой черты для экранирования символа новой строки, которая к тому же не работает, если после нее случайно поставлен пробел.
Переменные, которым присвоено значение в операторе :=, остаются доступными и после возврата из включения или выражения – в отличие от локальных переменных, определенных в функции. В документе PEP 572 область видимости оператора := определена как объемлющая функция, если только соответствующая переменная не является частью объявления global или nonlocal.
Если мы хотим произвести сопоставление (match) произвольной последовательности-субъекта, начинающейся с str и заканчивающейся вложенной последовательностью из двух float, то можем написать:
Здесь *_ сопоставляется с любым числом элементов без привязки их к переменной. Если вместо *_ использовать *extra, то с переменной extra будет связан список list, содержащий 0 или более элементов.
В NumPy … используется для сокращенного задания среза многомерного массива; например, если x – четырехмерный массив, то x[i, ...] – то же самое, что x[i, :, :, :,]. Имя класса ellipsis записывается строчными буквами, а его экземпляр – встроенный объект Ellipsis. Точно так же обстоит дело с классом bool и его экземплярами True и False.
Остерегайтесь выражений вида a * n, где a – последовательность, содержащая изменяемые элементы, потому что результат может оказаться неожиданным. Например, при попытке инициализировать список списков my_list = [[]] * 3 получится список, содержащий три ссылки на один и тот же внутренний список, хотя вы, скорее всего, хотели не этого.
Кратная конкатенация неизменяемых последовательностей выполняется неэффективно, потому что вместо добавления новых элементов интерпретатор вынужден копировать всю конечную последовательность, чтобы создать новую с добавленными элементами.
Строка my_dict.setdefault(key, []).append(new_value) дает такой же результат, как
… с тем отличием, что во втором фрагменте производится по меньшей мере два поиска ключа (три, если ключ не найден), тогда как setdefault довольствуется единственным поиском.
collections.ChainMap хранит список отображений, так что их можно просматривать как единое целое. Поиск производится в каждом отображении в порядке их перечисления в конструкторе и завершается успешно, если ключ найден хотя бы в одном. Например:
1
6
MappingProxyType можно использовать для защиты словаря от записи:
По умолчанию любой экземпляр пользовательского класса считается истинным, но положение меняется, если реализован хотя бы один из методов bool или len. Функция bool(x), по существу, вызывает x.bool() и использует полученный результат. Если метод bool не реализован, то Python пытается вызвать x.len() и при получении нуля функция bool возвращает False. В противном случае bool возвращает True.
В программе на Python переход на другую строку внутри пар скобок [], {} и () игнорируется. Поэтому при построении многострочных списков, списковых включений, генераторных выражений, словарей и прочего можно обходиться без косой черты для экранирования символа новой строки, которая к тому же не работает, если после нее случайно поставлен пробел.
Переменные, которым присвоено значение в операторе :=, остаются доступными и после возврата из включения или выражения – в отличие от локальных переменных, определенных в функции. В документе PEP 572 область видимости оператора := определена как объемлющая функция, если только соответствующая переменная не является частью объявления global или nonlocal.
>>> x = 'ABC'
>>> codes = [last := ord(c) for c in x]
>>> last
67
Если мы хотим произвести сопоставление (match) произвольной последовательности-субъекта, начинающейся с str и заканчивающейся вложенной последовательностью из двух float, то можем написать:
case [str(name), *_, (float(lat), float(lon))]:
Здесь *_ сопоставляется с любым числом элементов без привязки их к переменной. Если вместо *_ использовать *extra, то с переменной extra будет связан список list, содержащий 0 или более элементов.
В NumPy … используется для сокращенного задания среза многомерного массива; например, если x – четырехмерный массив, то x[i, ...] – то же самое, что x[i, :, :, :,]. Имя класса ellipsis записывается строчными буквами, а его экземпляр – встроенный объект Ellipsis. Точно так же обстоит дело с классом bool и его экземплярами True и False.
Остерегайтесь выражений вида a * n, где a – последовательность, содержащая изменяемые элементы, потому что результат может оказаться неожиданным. Например, при попытке инициализировать список списков my_list = [[]] * 3 получится список, содержащий три ссылки на один и тот же внутренний список, хотя вы, скорее всего, хотели не этого.
Кратная конкатенация неизменяемых последовательностей выполняется неэффективно, потому что вместо добавления новых элементов интерпретатор вынужден копировать всю конечную последовательность, чтобы создать новую с добавленными элементами.
Строка my_dict.setdefault(key, []).append(new_value) дает такой же результат, как
if key not in my_dict:
my_dict[key] = []
my_dict[key].append(new_value)
… с тем отличием, что во втором фрагменте производится по меньшей мере два поиска ключа (три, если ключ не найден), тогда как setdefault довольствуется единственным поиском.
collections.ChainMap хранит список отображений, так что их можно просматривать как единое целое. Поиск производится в каждом отображении в порядке их перечисления в конструкторе и завершается успешно, если ключ найден хотя бы в одном. Например:
>>> d1 = dict(a=1, b=3)
>>> d2 = dict(a=2, b=4, c=6)
>>> from collections import ChainMap
>>> chain = ChainMap(d1, d2)
>>> chain['a']
1
>>> chain['c']
6
MappingProxyType можно использовать для защиты словаря от записи:
from types import MappingProxyType
>>> d = {1: 'A'}
>>> d_proxy = MappingProxyType(d)
>>> d_proxy
mappingproxy({1: 'A'})
>>> d_proxy[1]
'A'
>>> d_proxy[2] = 'x'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment
#python #codegems
Для экономии памяти избегайте создания атрибутов экземпляров вне метода init. По умолчанию Python хранит атрибуты экземпляров в специальном атрибуте dict, который представляет собой словарь, являющийся принадлежностью экземпляра. С тех пор как в версии Python 3.3 было реализовано предложение PEP 412 «Key-Sharing Dictionary», экземпляры класса могут разделять общую хеш-таблицу, хранящуюся в самом классе. На эту общую хеш-таблицу ссылаются атрибуты dict каждого нового экземпляра, имеющего такие же имена атрибутов, что и первый экземпляр этого класса, возвращенный init.
Тогда dict в каждом экземпляре может хранить только собственные значения атрибутов в виде простого массива указателей. Добавление атрибута экземпляра после возврата из init заставляет Python создать новую хеш-таблицу для хранения dict только одного этого экземпляра (такое поведение подразумевалось по умолчанию для всех экземпляров до версии Python 3.3). Согласно PEP 412, эта оптимизация сокращает потребление памяти в объектно-ориентированных программах на 10–20%.
Если вы хотите устранить дубликаты, сохранив при этом порядок первого вхождения каждого элемента, можете воспользоваться простым словарем dict:
dict_keys и dict_items реализуют специальные методы для поддержки операторов над множествами & (пересечение), | (объединение), - (разность) и ^ (симметрическая разность). Например, с помощью & легко получить ключи, встречающиеся в двух словарях:
Представление dict_items работает как множество, только если все значения в словаре допускают хеширование. Попытка применить операцию над множествами к представлению dict_items с нехешируемыми значениями приводит к исключению TypeError: unhashable type 'T', где T – тип недопустимого значения. С другой стороны, представление dict_keys всегда можно использовать как множество, потому что все ключи словаря являются хешируемыми по определению. Применение операторов множества к представлениям позволяет отказаться от многочисленных циклов и условных предложений при исследовании содержимого словарей. Заставьте эффективную реализацию Python, написанную на C, работать для вас!
Грег Гандербергер выступает за то, чтобы и дальше использовать класс collections.OrderedDict на том основании, что «явное лучше неявного», а также ради обратной совместимости и потому что некоторые инструменты и библиотеки предполагают, что порядок ключей в dict несуществен.
Истоки JSON следует искать в JavaScript, но так получилось, что это почти точное подмножество синтаксиса Python. JSON совместим с Python во всем, кроме написания значений true, false и null. Армин Ронахер пишет, что ему понравилось «подправить» глобальное пространство имен Python, добавив совместимые с JSON псевдонимы для символов Python True, False и None, так что теперь он может копировать JSON прямо на консоль. Вот как выглядит его идея:
Калеб Хэттинг предлагает всегда использовать кодек UTF-8-SIG при чтении файлов в кодировке UTF-8. Это безвредно, потому что UTF-8-SIG правильно читает файлы с BOM и без BOM и не возвращает сам символ BOM.
Код, который должен работать на разных машинах или в разных ситуациях, не должен зависеть от кодировки по умолчанию. Всегда явно задавайте аргумент encoding= при открытии текстовых файлов, потому что умолчания могут зависеть от машины и даже меняться на одной и той же машине.
Для экономии памяти избегайте создания атрибутов экземпляров вне метода init. По умолчанию Python хранит атрибуты экземпляров в специальном атрибуте dict, который представляет собой словарь, являющийся принадлежностью экземпляра. С тех пор как в версии Python 3.3 было реализовано предложение PEP 412 «Key-Sharing Dictionary», экземпляры класса могут разделять общую хеш-таблицу, хранящуюся в самом классе. На эту общую хеш-таблицу ссылаются атрибуты dict каждого нового экземпляра, имеющего такие же имена атрибутов, что и первый экземпляр этого класса, возвращенный init.
Тогда dict в каждом экземпляре может хранить только собственные значения атрибутов в виде простого массива указателей. Добавление атрибута экземпляра после возврата из init заставляет Python создать новую хеш-таблицу для хранения dict только одного этого экземпляра (такое поведение подразумевалось по умолчанию для всех экземпляров до версии Python 3.3). Согласно PEP 412, эта оптимизация сокращает потребление памяти в объектно-ориентированных программах на 10–20%.
Если вы хотите устранить дубликаты, сохранив при этом порядок первого вхождения каждого элемента, можете воспользоваться простым словарем dict:
>>> dict.fromkeys(l).keys()
dict_keys(['spam', 'eggs', 'bacon'])
dict_keys и dict_items реализуют специальные методы для поддержки операторов над множествами & (пересечение), | (объединение), - (разность) и ^ (симметрическая разность). Например, с помощью & легко получить ключи, встречающиеся в двух словарях:
>>> d1 = dict(a=1, b=2, c=3, d=4)
>>> d2 = dict(b=20, d=40, e=50)
>>> d1.keys() & d2.keys()
{'b', 'd'}
Представление dict_items работает как множество, только если все значения в словаре допускают хеширование. Попытка применить операцию над множествами к представлению dict_items с нехешируемыми значениями приводит к исключению TypeError: unhashable type 'T', где T – тип недопустимого значения. С другой стороны, представление dict_keys всегда можно использовать как множество, потому что все ключи словаря являются хешируемыми по определению. Применение операторов множества к представлениям позволяет отказаться от многочисленных циклов и условных предложений при исследовании содержимого словарей. Заставьте эффективную реализацию Python, написанную на C, работать для вас!
Грег Гандербергер выступает за то, чтобы и дальше использовать класс collections.OrderedDict на том основании, что «явное лучше неявного», а также ради обратной совместимости и потому что некоторые инструменты и библиотеки предполагают, что порядок ключей в dict несуществен.
Истоки JSON следует искать в JavaScript, но так получилось, что это почти точное подмножество синтаксиса Python. JSON совместим с Python во всем, кроме написания значений true, false и null. Армин Ронахер пишет, что ему понравилось «подправить» глобальное пространство имен Python, добавив совместимые с JSON псевдонимы для символов Python True, False и None, так что теперь он может копировать JSON прямо на консоль. Вот как выглядит его идея:
>>> true, false, null = True, False, None
>>> fruit = {
... "type": "banana",
... "avg_weight": 123.2,
... "edible_peel": false,
... "species": ["acuminata", "balbisiana", "paradisiaca"],
... "issues": null,
... }
>>> fruit
{'type': 'banana', 'avg_weight': 123.2, 'edible_peel': False,
'species': ['acuminata', 'balbisiana', 'paradisiaca'], 'issues':
None}
Калеб Хэттинг предлагает всегда использовать кодек UTF-8-SIG при чтении файлов в кодировке UTF-8. Это безвредно, потому что UTF-8-SIG правильно читает файлы с BOM и без BOM и не возвращает сам символ BOM.
Код, который должен работать на разных машинах или в разных ситуациях, не должен зависеть от кодировки по умолчанию. Всегда явно задавайте аргумент encoding= при открытии текстовых файлов, потому что умолчания могут зависеть от машины и даже меняться на одной и той же машине.
#python #codegems
Формы нормализации NFKC и NFKD следует применять с осторожностью и только в особых случаях, например для поиска и индексирования, а не для постоянного хранения текста, поскольку выполняемые ими преобразования могут приводить к потере данных. Формы нормализации NFC и NFD безопасны и позволяют достаточно осмысленно сравнивать Unicode-строки. Для большинства приложений NFC – наилучшая нормализованная форма.
Для удаления всех диакритических знаков из str можно
1) Разложить все символы на базовые и модифицирующие.
2) Найти все модифицирующие символы.
3) Произвести обратную композицию:
Стандартный способ сортировки не-ASCII текстов в Python – функция locale.strxfrm, которая, «преобразует строку, так чтобы ее можно было использовать в сравнениях с учетом локали». Чтобы можно было воспользоваться функцией locale.strxfrm, необходимо сначала установить локаль, отвечающую нуждам приложения, и надеяться, что ОС ее поддерживает. В системах на базе GNU/Linux (Ubuntu 14.04) при выборе локали pt_BR нужный результат дает последовательность команд
Типизированный именованный кортеж можно построить, задав поля в виде именованных аргументов:
Этот код проще читать, а кроме того, он позволяет задать отображение полей на типы в виде **fields_and_types.
Ключевое различие между построителями классов dataclass/namedtuple/NamedTuple – тот факт, что collections.namedtuple и typing.NamedTuple строят подклассы tuple, поэтому экземпляры оказываются неизменяемыми. По умолчанию @dataclass порождает изменяемые классы. Но декоратор принимает именованный аргумент frozen, показанный в примере 5.3. Если frozen=True, то класс возбудит исключение при попытке присвоить какому-либо полю значение после инициализации экземпляра.
Экземпляры класса, построенного с помощью namedtuple, потребляют ровно столько памяти, сколько кортежи, потому что имена полей хранятся в определении класса.
@dataclass эмулирует неизменяемость, генерируя методы setattr и delattr, которые возбуждают исключение dataclass.FrozenInstanceError – подкласс AttributeError, – когда пользователь пытается изменить или удалить поле. Если frozen=False (по умолчанию), то @dataclass установит атрибут hash равным None, сигнализируя о том, что экземпляры не хешируемые, и тем самым отменив метод hash, унаследованный от суперкласса.
Опция default в классе данных существует, потому что обращение к field заменяет значение по умолчанию в аннотации поля. Если мы хотим создать поле athlete со значением по умолчанию False, но не включать это поле в метод repr, то должны будем написать такое определение:
Декоратору @dataclass безразличны типы в аннотациях, за исключением двух случаев. Один из них такой: если тип атрибута равен ClassVar, то для него не генерируется поле экземпляра. Второй случай, когда тип поля имеет значение для @dataclass, – объявление переменных только для инициализации.
Пример из документации по модулю dataclasses, иллюстрирующий использование переменных только для инициализации:
Формы нормализации NFKC и NFKD следует применять с осторожностью и только в особых случаях, например для поиска и индексирования, а не для постоянного хранения текста, поскольку выполняемые ими преобразования могут приводить к потере данных. Формы нормализации NFC и NFD безопасны и позволяют достаточно осмысленно сравнивать Unicode-строки. Для большинства приложений NFC – наилучшая нормализованная форма.
Для удаления всех диакритических знаков из str можно
1) Разложить все символы на базовые и модифицирующие.
2) Найти все модифицирующие символы.
3) Произвести обратную композицию:
import unicodedata
import string
def shave_marks(txt):
"""Remove all diacritic marks"""
norm_txt = unicodedata.normalize('NFD', txt)
shaved = ''.join(c for c in norm_txt if not unicodedata.combining(c))
return unicodedata.normalize('NFC'shaved)
Стандартный способ сортировки не-ASCII текстов в Python – функция locale.strxfrm, которая, «преобразует строку, так чтобы ее можно было использовать в сравнениях с учетом локали». Чтобы можно было воспользоваться функцией locale.strxfrm, необходимо сначала установить локаль, отвечающую нуждам приложения, и надеяться, что ОС ее поддерживает. В системах на базе GNU/Linux (Ubuntu 14.04) при выборе локали pt_BR нужный результат дает последовательность команд
import locale
my_locale = locale.setlocale(locale.LC_COLLATE, 'pt_BR.UTF-8')
print(my_locale)
fruits = ['caju', 'atemoia', 'cajá', 'açaí', 'acerola']
sorted_fruits = sorted(fruits, key=locale.strxfrm)
print(sorted_fruits)
'pt_BR.UTF-8'
['açaí', 'acerola', 'atemoia', 'cajá', 'caju']
Типизированный именованный кортеж можно построить, задав поля в виде именованных аргументов:
Coordinate = typing.NamedTuple('Coordinate', lat=float, lon=float)Этот код проще читать, а кроме того, он позволяет задать отображение полей на типы в виде **fields_and_types.
Ключевое различие между построителями классов dataclass/namedtuple/NamedTuple – тот факт, что collections.namedtuple и typing.NamedTuple строят подклассы tuple, поэтому экземпляры оказываются неизменяемыми. По умолчанию @dataclass порождает изменяемые классы. Но декоратор принимает именованный аргумент frozen, показанный в примере 5.3. Если frozen=True, то класс возбудит исключение при попытке присвоить какому-либо полю значение после инициализации экземпляра.
Экземпляры класса, построенного с помощью namedtuple, потребляют ровно столько памяти, сколько кортежи, потому что имена полей хранятся в определении класса.
@dataclass эмулирует неизменяемость, генерируя методы setattr и delattr, которые возбуждают исключение dataclass.FrozenInstanceError – подкласс AttributeError, – когда пользователь пытается изменить или удалить поле. Если frozen=False (по умолчанию), то @dataclass установит атрибут hash равным None, сигнализируя о том, что экземпляры не хешируемые, и тем самым отменив метод hash, унаследованный от суперкласса.
Опция default в классе данных существует, потому что обращение к field заменяет значение по умолчанию в аннотации поля. Если мы хотим создать поле athlete со значением по умолчанию False, но не включать это поле в метод repr, то должны будем написать такое определение:
@dataclass
class ClubMember:
name: str
guests: list = field(default_factory=list)
athlete: bool = field(default=False, repr=False)
Декоратору @dataclass безразличны типы в аннотациях, за исключением двух случаев. Один из них такой: если тип атрибута равен ClassVar, то для него не генерируется поле экземпляра. Второй случай, когда тип поля имеет значение для @dataclass, – объявление переменных только для инициализации.
Пример из документации по модулю dataclasses, иллюстрирующий использование переменных только для инициализации:
@dataclass
class C:
i: int
j: int = None
database: InitVar[DatabaseType] = None
def __post_init__(self, database):
if self.j is None and database is not None:
self.j = database.lookup('j')
c = C(10, database=my_database)
#python #codegems
Если используется @dataclass, то аннотации типов перестают быть факультативными. Последние семь лет, с момента выхода документа PEP 484 «Type Hints», нам обещали, что аннотации всегда будут необязательными. А теперь мы имеем важное новое средство языка, которое без них работать не может. Если вам не нравится весь этот уклон в сторону статической типизации, то можете вместо этого пользоваться attrs.
Синтаксис, предлагаемый в PEP 526 для аннотирования атрибутов класса и экземпляра, выворачивает наизнанку установившееся соглашение о предложениях class: все, что объявлено на верхнем уровне блока class, является атрибутом класса (методы – тоже атрибуты класса). А в PEP 526 и @dataclass всякий атрибут, объявленный на верхнем уровне с аннотацией типа, становится атрибутом экземпляра:
Но если аннотаций типов нет, то мы внезапно возвращаемся в старые добрые времена, когда объявления, находящиеся на верхнем уровне класса, принадлежали самому классу, а не его экземплярам:
Наконец, если мы хотим аннотировать атрибут класса типом, то не можем использовать регулярные типы, потому что тогда получим атрибут экземпляра. И приходится прибегать к аннотации псевдотипа ClassVar:
Если используется @dataclass, то аннотации типов перестают быть факультативными. Последние семь лет, с момента выхода документа PEP 484 «Type Hints», нам обещали, что аннотации всегда будут необязательными. А теперь мы имеем важное новое средство языка, которое без них работать не может. Если вам не нравится весь этот уклон в сторону статической типизации, то можете вместо этого пользоваться attrs.
Синтаксис, предлагаемый в PEP 526 для аннотирования атрибутов класса и экземпляра, выворачивает наизнанку установившееся соглашение о предложениях class: все, что объявлено на верхнем уровне блока class, является атрибутом класса (методы – тоже атрибуты класса). А в PEP 526 и @dataclass всякий атрибут, объявленный на верхнем уровне с аннотацией типа, становится атрибутом экземпляра:
@dataclass
class Spam:
repeat: int # атрибут экземпляра
Но если аннотаций типов нет, то мы внезапно возвращаемся в старые добрые времена, когда объявления, находящиеся на верхнем уровне класса, принадлежали самому классу, а не его экземплярам:
@dataclass
class Spam:
repeat = 99 # атрибут класса!
Наконец, если мы хотим аннотировать атрибут класса типом, то не можем использовать регулярные типы, потому что тогда получим атрибут экземпляра. И приходится прибегать к аннотации псевдотипа ClassVar:
@dataclass
class Spam:
repeat: ClassVar[int] = 99 # ррррр!
#python #codegems
Для списков и других изменяемых последовательностей присваивание l2 = l1[:] также создает копию. Однако при использовании конструктора и оператора [:] создается поверхностная (shallow) копия (т. е. дублируется только самый внешний контейнер, который заполняется ссылками на те же элементы, что хранятся в исходном контейнере). Это экономит память и не создает проблем, если все элементы неизменяемые. Однако при наличии изменяемых элементов можно столкнуться с неприятными сюрпризами.
Слабые ссылки на объект не увеличивают счетчик ссылок. Таким образом, слабая ссылка не препятствует уничтожению объекта ссылки сборщиком мусора. Слабые ссылки полезны для кеширования, поскольку мы не хотим, чтобы кешированный объект оставался жив только потому, что на него ссылается сам кеш.
Для кортежа t конструкция t[:] не создает копию, а возвращает ссылку на сам объект. Ссылку на исходный кортеж мы получаем также, написав tuple(t). Такое же поведение свойственно экземплярам классов str, bytes и frozenset. frozenset – не последовательность, поэтому, когда fs является объектом frozenset, конструкция fs[:] не работает. Но fs.copy() дает точно такой же эффект: обманывает нас и возвращает ссылку на тот же объект, а вовсе не на его копию.
В некоторых ситуациях полезно иметь ссылку, которая сама по себе не удерживает объект «в мире живых». Примером может служить класс, желающий отслеживать все свои экземпляры. Это можно сделать с помощью слабых ссылок – низкоуровневого механизма, на базе которого построены более полезные коллекции WeakValueDictionary, WeakKeyDictionary, WeakSet и функция finalize – все из модуля weakref.
На самом деле тип объекта тоже можно изменить, просто присвоив другой класс его атрибуту class, но это неприкрытое зло.
Функцией высшего порядка называется функция, которая принимает функцию в качестве аргумента или возвращает в качестве значения. Примером может служить функция map. Другой пример – встроенная функция sorted: ее необязательный аргумент key позволяет задать функцию, которая применяется к каждому сортируемому элементу.
Если в классе определен метод call, то его экземпляры можно вызывать как функции. Обычно при вызове класса создается экземпляр именно этого класса, но такое поведение можно изменить, переопределив метод new.
Класс, в котором реализован метод call, – простой способ создать похожий на функцию объект, обладающий внутренним состоянием, которое должно сохраняться между вызовами. Хороший пример – декоратор. Декоратор должен быть вызываемым объектом, и иногда удобно иметь возможность «запоминать» что-то между вызовами декоратора (например, в случае кеширования результатов длительных вычислений для последующего использования) или разбить сложную реализацию на несколько методов.
Стремление к стопроцентному покрытию аннотациями типов означает, что вы применяете аннотирование без ясной цели, просто ради красивых показателей. К тому же это будет мешать команде добиться максимума от мощи и гибкости Python. Код без аннотаций типов должен без колебаний приниматься, если аннотации сделали бы API менее удобным для пользователя или без нужды усложнили бы реализацию.
Если факультативный параметр имеет изменяемый тип, то None – единственно разумное значение по умолчанию
К работе с утиной типизацией проще приступить и она обладает большей гибкостью, но возможность, что неподдерживаемые операции приведут к ошибке во время выполнения, остается. Номинальная типизация обнаруживает ошибки до начала выполнения, но иногда отвергает код, который работал бы правильно.
Для списков и других изменяемых последовательностей присваивание l2 = l1[:] также создает копию. Однако при использовании конструктора и оператора [:] создается поверхностная (shallow) копия (т. е. дублируется только самый внешний контейнер, который заполняется ссылками на те же элементы, что хранятся в исходном контейнере). Это экономит память и не создает проблем, если все элементы неизменяемые. Однако при наличии изменяемых элементов можно столкнуться с неприятными сюрпризами.
Слабые ссылки на объект не увеличивают счетчик ссылок. Таким образом, слабая ссылка не препятствует уничтожению объекта ссылки сборщиком мусора. Слабые ссылки полезны для кеширования, поскольку мы не хотим, чтобы кешированный объект оставался жив только потому, что на него ссылается сам кеш.
Для кортежа t конструкция t[:] не создает копию, а возвращает ссылку на сам объект. Ссылку на исходный кортеж мы получаем также, написав tuple(t). Такое же поведение свойственно экземплярам классов str, bytes и frozenset. frozenset – не последовательность, поэтому, когда fs является объектом frozenset, конструкция fs[:] не работает. Но fs.copy() дает точно такой же эффект: обманывает нас и возвращает ссылку на тот же объект, а вовсе не на его копию.
В некоторых ситуациях полезно иметь ссылку, которая сама по себе не удерживает объект «в мире живых». Примером может служить класс, желающий отслеживать все свои экземпляры. Это можно сделать с помощью слабых ссылок – низкоуровневого механизма, на базе которого построены более полезные коллекции WeakValueDictionary, WeakKeyDictionary, WeakSet и функция finalize – все из модуля weakref.
На самом деле тип объекта тоже можно изменить, просто присвоив другой класс его атрибуту class, но это неприкрытое зло.
Функцией высшего порядка называется функция, которая принимает функцию в качестве аргумента или возвращает в качестве значения. Примером может служить функция map. Другой пример – встроенная функция sorted: ее необязательный аргумент key позволяет задать функцию, которая применяется к каждому сортируемому элементу.
Если в классе определен метод call, то его экземпляры можно вызывать как функции. Обычно при вызове класса создается экземпляр именно этого класса, но такое поведение можно изменить, переопределив метод new.
Класс, в котором реализован метод call, – простой способ создать похожий на функцию объект, обладающий внутренним состоянием, которое должно сохраняться между вызовами. Хороший пример – декоратор. Декоратор должен быть вызываемым объектом, и иногда удобно иметь возможность «запоминать» что-то между вызовами декоратора (например, в случае кеширования результатов длительных вычислений для последующего использования) или разбить сложную реализацию на несколько методов.
Стремление к стопроцентному покрытию аннотациями типов означает, что вы применяете аннотирование без ясной цели, просто ради красивых показателей. К тому же это будет мешать команде добиться максимума от мощи и гибкости Python. Код без аннотаций типов должен без колебаний приниматься, если аннотации сделали бы API менее удобным для пользователя или без нужды усложнили бы реализацию.
Если факультативный параметр имеет изменяемый тип, то None – единственно разумное значение по умолчанию
К работе с утиной типизацией проще приступить и она обладает большей гибкостью, но возможность, что неподдерживаемые операции приведут к ошибке во время выполнения, остается. Номинальная типизация обнаруживает ошибки до начала выполнения, но иногда отвергает код, который работал бы правильно.
#python #codegems
Any – необычный тип, который располагается и в самом верху, и в самом низу иерархии типов. Это одновременно и самый общий тип (т. е. аргумент n: Any принимает значения любого типа), и самый специализированный, т. е. поддерживает любую операцию. По крайней мере, именно так средство проверки типов воспринимает Any. Разумеется, никакой тип не может поддерживать все возможные операции, поэтому использование Any лишает средство проверки типов возможности выполнить свою основную миссию: обнаруживать потенциально некорректные операции до того, как программа аварийно завершится с исключением во время выполнения.
Начиная с версии Python 3.10 мы можем писать str | bytes вместо Union[str, bytes]. Это короче и не нужно импортировать Optional и Union из модуля typing. Сравните старый и новый синтаксисы аннотаций типов для параметра plural функции show_count:
plural: Optional[str] = None # до
plural: str | None = None # после
Оператор | можно также применять в сочетании с isinstance и issubclass для построения второго аргумента: isinstance(x,int | str).
Есть функции, которые принимают аргументы типа str или bytes, но возвращают str, если аргумент имел тип str, и bytes, если он имел тип bytes. В таких случаях тип возвращаемого значения определяется типом входа, поэтому Union – не совсем подходящее решение. Чтобы правильно аннотировать подобные функции, нам нужна переменная-тип TypeVar.
Чтобы включить в аннотацию кортеж неопределенной длины, используемый как неизменяемый список, необходимо задать один тип, за которым следуют запятая и многоточие ...
Например, tuple[int, ...] – кортеж, состоящий из элементов типа int. Многоточие означает, что допустимо любое число элементов >= 1. Не существует способа задать поля разных типов в кортежах произвольной длины.
Аннотации stuff: tuple[Any, ...] и stuff: tuple означают одно и то же: stuff является кортежем неопределенной длины, содержащим объекты любого типа.
В общем случае в аннотациях типов параметров лучше использовать abc.Mapping или abc.MutableMapping, а не dict (или typing.Dict в унаследованном коде).
Идея специального типа TypeAlias в том, чтобы сделать создаваемые псевдонимы типов хорошо видимыми и упростить для них проверку типов. Начиная с версии Python 3.10 это рекомендуемый способ создания псевдонимов типов:
typing.Protocol дает нам статическую утиную типизацию.
Тип NoReturn - это специальный тип, использующийся только для аннотирования типов возвращаемых значений функций, которые вообще не возвращают управления. Обычно они существуют, чтобы возбуждать исключение. В стандартной библиотеке десятки таких функций. Например, функция sys.exit() возбуждает исключение SystemExit, чтобы завершить процесс Python.
Any – необычный тип, который располагается и в самом верху, и в самом низу иерархии типов. Это одновременно и самый общий тип (т. е. аргумент n: Any принимает значения любого типа), и самый специализированный, т. е. поддерживает любую операцию. По крайней мере, именно так средство проверки типов воспринимает Any. Разумеется, никакой тип не может поддерживать все возможные операции, поэтому использование Any лишает средство проверки типов возможности выполнить свою основную миссию: обнаруживать потенциально некорректные операции до того, как программа аварийно завершится с исключением во время выполнения.
Начиная с версии Python 3.10 мы можем писать str | bytes вместо Union[str, bytes]. Это короче и не нужно импортировать Optional и Union из модуля typing. Сравните старый и новый синтаксисы аннотаций типов для параметра plural функции show_count:
plural: Optional[str] = None # до
plural: str | None = None # после
Оператор | можно также применять в сочетании с isinstance и issubclass для построения второго аргумента: isinstance(x,int | str).
Есть функции, которые принимают аргументы типа str или bytes, но возвращают str, если аргумент имел тип str, и bytes, если он имел тип bytes. В таких случаях тип возвращаемого значения определяется типом входа, поэтому Union – не совсем подходящее решение. Чтобы правильно аннотировать подобные функции, нам нужна переменная-тип TypeVar.
Чтобы включить в аннотацию кортеж неопределенной длины, используемый как неизменяемый список, необходимо задать один тип, за которым следуют запятая и многоточие ...
Например, tuple[int, ...] – кортеж, состоящий из элементов типа int. Многоточие означает, что допустимо любое число элементов >= 1. Не существует способа задать поля разных типов в кортежах произвольной длины.
Аннотации stuff: tuple[Any, ...] и stuff: tuple означают одно и то же: stuff является кортежем неопределенной длины, содержащим объекты любого типа.
В общем случае в аннотациях типов параметров лучше использовать abc.Mapping или abc.MutableMapping, а не dict (или typing.Dict в унаследованном коде).
Идея специального типа TypeAlias в том, чтобы сделать создаваемые псевдонимы типов хорошо видимыми и упростить для них проверку типов. Начиная с версии Python 3.10 это рекомендуемый способ создания псевдонимов типов:
typing.Protocol дает нам статическую утиную типизацию.
Тип NoReturn - это специальный тип, использующийся только для аннотирования типов возвращаемых значений функций, которые вообще не возвращают управления. Обычно они существуют, чтобы возбуждать исключение. В стандартной библиотеке десятки таких функций. Например, функция sys.exit() возбуждает исключение SystemExit, чтобы завершить процесс Python.
#python #codegems
Нотация / для чисто позиционных параметров появилась в версии Python 3.8. В Python 3.7 и более ранних версиях она приводит к синтаксической ошибке. В документе PEP 484 предлагается соглашение: имя любого чисто позиционного параметра начинать с двух знаков подчеркивания.
Переменные-типы (TypeVar) повышают гибкость аннотаций типов, не жертвуя типобезопасностью. Параметризованные обобщенные типы становятся еще более выразительными при использовании протоколов. Тип Protocol появился только в версии Python 3.8 и пока еще не получил широкого распространения, но его важность невозможно переоценить. Protocol открывает возможность для статической утиной типизации, мосту между ядром Python, основанным на утиной типизации, и номинальной типизацией, позволяющей средствам статической проверки типов отлавливать ошибки.
Во время экспериментов тесты и аннотации типов не особенно полезны. Они только тормозят работу.
Если кодирование – не ваша профессия, а лишь полезный инструмент, применяемый в профессиональных занятиях, или нечто такое, что вы изучаете ради удовольствия, то, пожалуй, аннотации типов нужны вам не больше, чем жесткие ботинки и металлические набойки большинству велосипедистов. Просто кодируйте.
Одно из самых плохо понимаемых зарезервированных слов в Python – nonlocal, оно появилось в версии Python 3.0. Программист на Python может безбедно существовать, и не используя его, если будет строго придерживаться объектно-ориентированной диеты, основанной на классах. Но если вы захотите реализовать собственные декораторы функций, то должны досконально разбираться в замыканиях, а тогда потребность в слове nonlocal становится очевидной.
Декораторы функций выполняются сразу после импорта модуля.
Замыкание (closure) – это функция, которая запоминает привязки свободных переменных, существовавшие на момент определения функции, так что их можно использовать впоследствии при вызове функции, когда область видимости, в которой она была определена, уже не существует. Отметим, что единственная ситуация, когда функции может понадобиться доступ к внешним неглобальным переменным, – это когда она вложена в другую функцию и эти переменные являются частью локальной области видимости внешней функции.
Преимущество @singledispath – в поддержке модульного расширения: каждый модуль может зарегистрировать специализированную функцию для того типа, который поддерживает.
Леннарт Регебро считает, что декораторы лучше писать как классы, реализующие метод call, а не как функции.
В некоторых случаях функции могут проделать ту же работу, что и классы, а код при этом получается проще и короче.
По определению, инструменты статического анализа не способны понять динамическую структуру Python. Если тупо следовать каждому их совету, то мы начнем писать угрюмый и многословный код а-ля Java с синтаксисом Python.
Декоратор classmethod, очевидно, полезен, но мне очень редко встречались хорошие примеры употребления staticmethod. Быть может, функция тесно связана с классом, хотя и не залезает в его «потроха», так что лучше разместить ее код поблизости. Но даже если так, размещение функции сразу до или после класса в том же модуле – это достаточно близко для любых практических целей.
В модулях одиночный подчерк в начале имени верхнего уровня имеет специальный смысл: если написать from mymod import *, то имена с префиксом _ не будут импортироваться из mymod. Но ничто не мешает явно написать from mymod import _privatefunc.
Нотация / для чисто позиционных параметров появилась в версии Python 3.8. В Python 3.7 и более ранних версиях она приводит к синтаксической ошибке. В документе PEP 484 предлагается соглашение: имя любого чисто позиционного параметра начинать с двух знаков подчеркивания.
Переменные-типы (TypeVar) повышают гибкость аннотаций типов, не жертвуя типобезопасностью. Параметризованные обобщенные типы становятся еще более выразительными при использовании протоколов. Тип Protocol появился только в версии Python 3.8 и пока еще не получил широкого распространения, но его важность невозможно переоценить. Protocol открывает возможность для статической утиной типизации, мосту между ядром Python, основанным на утиной типизации, и номинальной типизацией, позволяющей средствам статической проверки типов отлавливать ошибки.
Во время экспериментов тесты и аннотации типов не особенно полезны. Они только тормозят работу.
Если кодирование – не ваша профессия, а лишь полезный инструмент, применяемый в профессиональных занятиях, или нечто такое, что вы изучаете ради удовольствия, то, пожалуй, аннотации типов нужны вам не больше, чем жесткие ботинки и металлические набойки большинству велосипедистов. Просто кодируйте.
Одно из самых плохо понимаемых зарезервированных слов в Python – nonlocal, оно появилось в версии Python 3.0. Программист на Python может безбедно существовать, и не используя его, если будет строго придерживаться объектно-ориентированной диеты, основанной на классах. Но если вы захотите реализовать собственные декораторы функций, то должны досконально разбираться в замыканиях, а тогда потребность в слове nonlocal становится очевидной.
Декораторы функций выполняются сразу после импорта модуля.
Замыкание (closure) – это функция, которая запоминает привязки свободных переменных, существовавшие на момент определения функции, так что их можно использовать впоследствии при вызове функции, когда область видимости, в которой она была определена, уже не существует. Отметим, что единственная ситуация, когда функции может понадобиться доступ к внешним неглобальным переменным, – это когда она вложена в другую функцию и эти переменные являются частью локальной области видимости внешней функции.
Преимущество @singledispath – в поддержке модульного расширения: каждый модуль может зарегистрировать специализированную функцию для того типа, который поддерживает.
Леннарт Регебро считает, что декораторы лучше писать как классы, реализующие метод call, а не как функции.
import time
DEFAULT_FMT = '[{elapsed:0.8f}s] {name}({args}) -> {result}'
class clock:
def __init__(self, fmt=DEFAULT_FMT):
self.fmt = fmt
def __call__(self, func):
def clocked(*_args):
t0 = time.perf_counter()
_result = func(*_args)
elapsed = time.perf_counter() - t0
name = func.__name__
args = ', '.join(repr(arg) for arg in _args)
result = repr(_result)
print(self.fmt.format(**locals()))
return _result
return clocked
В некоторых случаях функции могут проделать ту же работу, что и классы, а код при этом получается проще и короче.
По определению, инструменты статического анализа не способны понять динамическую структуру Python. Если тупо следовать каждому их совету, то мы начнем писать угрюмый и многословный код а-ля Java с синтаксисом Python.
Декоратор classmethod, очевидно, полезен, но мне очень редко встречались хорошие примеры употребления staticmethod. Быть может, функция тесно связана с классом, хотя и не залезает в его «потроха», так что лучше разместить ее код поблизости. Но даже если так, размещение функции сразу до или после класса в том же модуле – это достаточно близко для любых практических целей.
В модулях одиночный подчерк в начале имени верхнего уровня имеет специальный смысл: если написать from mymod import *, то имена с префиксом _ не будут импортироваться из mymod. Но ничто не мешает явно написать from mymod import _privatefunc.
#python #codegems
Метод getattr вызывается интерпретатором, если поиск атрибута завершается неудачно. Иначе говоря, анализируя выражение my_obj.x, Python проверяет, есть ли у объекта my_obj атрибут с именем x; если нет, поиск повторяется в классе (my_obj.class), а затем вверх по иерархии наследования1. Если атрибут x все равно не найден, то вызывается метод getattr, определенный в классе my_obj, причем ему передается self и имя атрибута в виде строки (например, 'x').
При использовании reduce рекомендуется задавать третий аргумент, reduce(function, iterable, initializer), чтобы предотвратить появление исключения TypeError: reduce() of empty sequence with no initial value (отличное сообщение: описывается проблема и способ исправления).
zip останавливается, не выдавая предупреждения, как только один из итерируемых объектов оказывается исчерпанным. Функция itertools.zip_longest ведет себя иначе: она подставляет вместо отсутствующих значений необязательный аргумент fillvalue (по умолчанию None), поэтому генерирует кортежи, пока не окажется исчерпанным самый длинный итерируемый объект.В документе PEP 618 «Add Optional Length-Checking To zip» предложено добавить в zip факультативный аргумент strict, при наличии которого она ведет себя именно таким образом. Предложение реализовано в Python 3.10.
Функцию zip можно также использовать для транспонирования матрицы, представленной в виде вложенных итерируемых объектов. Например:
Защитное программирование – как контраварийное вождение: набор практических навыков, повышающих безопасность при столкновении с беспечными программистами – или водителями. Многие ошибки можно отловить только во время выполнения, даже в популярных статически типизированных языках.
В динамически типизированном языке принцип быстрого отказа – прекрасный совет по созданию более безопасных и удобных для сопровождения программ. Быстрый отказ означает, что нужно возбудить исключение как можно раньше, например отвергать недопустимые аргументы в самом начале тела функции.
Метод getattr вызывается интерпретатором, если поиск атрибута завершается неудачно. Иначе говоря, анализируя выражение my_obj.x, Python проверяет, есть ли у объекта my_obj атрибут с именем x; если нет, поиск повторяется в классе (my_obj.class), а затем вверх по иерархии наследования1. Если атрибут x все равно не найден, то вызывается метод getattr, определенный в классе my_obj, причем ему передается self и имя атрибута в виде строки (например, 'x').
При использовании reduce рекомендуется задавать третий аргумент, reduce(function, iterable, initializer), чтобы предотвратить появление исключения TypeError: reduce() of empty sequence with no initial value (отличное сообщение: описывается проблема и способ исправления).
zip останавливается, не выдавая предупреждения, как только один из итерируемых объектов оказывается исчерпанным. Функция itertools.zip_longest ведет себя иначе: она подставляет вместо отсутствующих значений необязательный аргумент fillvalue (по умолчанию None), поэтому генерирует кортежи, пока не окажется исчерпанным самый длинный итерируемый объект.В документе PEP 618 «Add Optional Length-Checking To zip» предложено добавить в zip факультативный аргумент strict, при наличии которого она ведет себя именно таким образом. Предложение реализовано в Python 3.10.
Функцию zip можно также использовать для транспонирования матрицы, представленной в виде вложенных итерируемых объектов. Например:
>>> a = [(1, 2, 3),
... (4, 5, 6)]
>>> list(zip(*a))
[(1, 4), (2, 5), (3, 6)]
Защитное программирование – как контраварийное вождение: набор практических навыков, повышающих безопасность при столкновении с беспечными программистами – или водителями. Многие ошибки можно отловить только во время выполнения, даже в популярных статически типизированных языках.
В динамически типизированном языке принцип быстрого отказа – прекрасный совет по созданию более безопасных и удобных для сопровождения программ. Быстрый отказ означает, что нужно возбудить исключение как можно раньше, например отвергать недопустимые аргументы в самом начале тела функции.