Marshal's channel
Photo
А, ну ясно, я дцп, ничего нового. Ток дцп особенное, с ним в армию берут, в отличии от настоящего
Отношение к компаниям, помогающим призывникам.
Дело в том, что как обычно, я офигиваю с предков. Они не очень радостно отнеслись к заказу услуг у одной из таких компаний.
Значит два человека, два мнения:
1. "Да зачем оно тебе надо, сейчас всех берут, всё равно в армию пойдешь". Вот это я просто офигел ля, слышать такое за ужином очень рад. Поддержка на уровне. Собсна, отвечаю на отвали, абсолютно не поддерживая тему. Не хочу даже слышать этого.
2. "Деньги в никуда, мог сам походить по врачам".
Не понимаю своих родных. Всё же очень просто! Когда мы хотим причу - идём к парикмахеру, когда хотим поесть - в какое-то заведение, где нам приготовят.
Когда я хочу узнать о непризывных заболеваниях, иметь помощь юриста чуть что и чтобы меня за ручку поводили по врачам - я обращаюсь к людям, которые в этом шарят.
Каждая услуга стоит денег. И да, всё можно сделать самостоятельно. Можно станком налысо побриться, а можно вкусное блюдо приготовить. А можно расписание болезней изучить, понять какие врачи и анализы тебе для этого нужны, самому это всё анализировать и складывать, а потом ещё составлять пакет документов, нести в военкомат, где тебя развернут, потому что больничка, в который ты делал, не котируется и скажут переделывать в другой.
Учитывая то, что это не прога, где я конечно лучше сам изучу че-нить, а не пойду заказывать у другого прогера, то вариант не изучать все эти болячки, не гуглить кучу раз, а просто ходить в назначенное время по больничкам и скидывать им результаты в телегу - мне идеально подходит.
Солидарны с моим мнением или больше бумеров саппортите?
Дело в том, что как обычно, я офигиваю с предков. Они не очень радостно отнеслись к заказу услуг у одной из таких компаний.
Значит два человека, два мнения:
1. "Да зачем оно тебе надо, сейчас всех берут, всё равно в армию пойдешь". Вот это я просто офигел ля, слышать такое за ужином очень рад. Поддержка на уровне. Собсна, отвечаю на отвали, абсолютно не поддерживая тему. Не хочу даже слышать этого.
2. "Деньги в никуда, мог сам походить по врачам".
Не понимаю своих родных. Всё же очень просто! Когда мы хотим причу - идём к парикмахеру, когда хотим поесть - в какое-то заведение, где нам приготовят.
Когда я хочу узнать о непризывных заболеваниях, иметь помощь юриста чуть что и чтобы меня за ручку поводили по врачам - я обращаюсь к людям, которые в этом шарят.
Каждая услуга стоит денег. И да, всё можно сделать самостоятельно. Можно станком налысо побриться, а можно вкусное блюдо приготовить. А можно расписание болезней изучить, понять какие врачи и анализы тебе для этого нужны, самому это всё анализировать и складывать, а потом ещё составлять пакет документов, нести в военкомат, где тебя развернут, потому что больничка, в который ты делал, не котируется и скажут переделывать в другой.
Учитывая то, что это не прога, где я конечно лучше сам изучу че-нить, а не пойду заказывать у другого прогера, то вариант не изучать все эти болячки, не гуглить кучу раз, а просто ходить в назначенное время по больничкам и скидывать им результаты в телегу - мне идеально подходит.
Солидарны с моим мнением или больше бумеров саппортите?
Давно хотел слезть с bootstrap'a, но в матириал лень. Изучал что есть ещё кроме этих двух и было все очень плачевно (года полтора назад, там представителей 5 достойных только, а из этих пригодных для использования 3).
В общем тут какой-то топ рандомный фреймворков для реакта - https://medium.com/javascript-in-plain-english/9627a955484d
Первый раз всех, кроме первого, вижу. Надо будет позалипать, а пока тут схороню.
Upd. Ааа, я вспомнил чего так мало нашел тогда. Я не шарил за React JS и скипал компонентные онли фреймворки
В общем тут какой-то топ рандомный фреймворков для реакта - https://medium.com/javascript-in-plain-english/9627a955484d
Первый раз всех, кроме первого, вижу. Надо будет позалипать, а пока тут схороню.
Upd. Ааа, я вспомнил чего так мало нашел тогда. Я не шарил за React JS и скипал компонентные онли фреймворки
Medium
Here Are 5 Useful React UI Component Frameworks
Make your UI much better
GitHub - новая страничка с уведомлениями
Не знаю как давно и как скоро я получил доступ к этой beta-фиче, по сравнению с другими, но увидел только сейчас. Годно.
Все боялись, что майки угробят гитхаб, но разве с тех пор была хоть одна какуля?
Upd. при переходе с уведомления на issue, например, вверху появляется дополнительная менюшка, где можно отписаться, сохранить в закладки, или нажать done - что вернет обратно к списку уведомлений, а это пометит как прочитанное. Так же там можно пометить уведомление как непрочитанное
Не знаю как давно и как скоро я получил доступ к этой beta-фиче, по сравнению с другими, но увидел только сейчас. Годно.
Все боялись, что майки угробят гитхаб, но разве с тех пор была хоть одна какуля?
Upd. при переходе с уведомления на issue, например, вверху появляется дополнительная менюшка, где можно отписаться, сохранить в закладки, или нажать done - что вернет обратно к списку уведомлений, а это пометит как прочитанное. Так же там можно пометить уведомление как непрочитанное
Forwarded from ∏ρ؃uñçτØρ Øπτµç∑ | 👁🗨››››
ОНЛАЙН КОНФА PROFUNCTOR TALKS
- если тебе есть что рассказать про разработку или околоразработку то ты можешь стать спикером
- онлайн формат: стрим, сотни/тысячи зрителей, никаких билетов и гостиниц, можно из дома сидя в трениках
- дружелюбное коммьюнити, новые знакомства, веселее чем ты ожидаешь
- дата: TO BE ANNOUNCED
- формат: 20 минут на выступление, 10 минут на вопросы
- ПОДАЙ ЗАЯВКУ пока есть свободные слоты
- если тебе есть что рассказать про разработку или околоразработку то ты можешь стать спикером
- онлайн формат: стрим, сотни/тысячи зрителей, никаких билетов и гостиниц, можно из дома сидя в трениках
- дружелюбное коммьюнити, новые знакомства, веселее чем ты ожидаешь
- дата: TO BE ANNOUNCED
- формат: 20 минут на выступление, 10 минут на вопросы
- ПОДАЙ ЗАЯВКУ пока есть свободные слоты
GitHub
GitHub is where people build software. More than 100 million people use GitHub to discover, fork, and contribute to over 330 million projects.
Собираюсь начать постить всякое про Python. Это пригодится и для технических собесов, и просто для себя (повторить изученное). Без особого углубления в детали и мелочи, поверхностно, сжато. Просто пробежаться по тому, что есть в Python'e, начиная с самого примитивного и непойми чем заканчивая. Буду пытаться находить какие-то интересные моменты.
Сам я на этом сейчас и сфокусирован. Пытаюсь ещё задачки решать на codeforces'e и с C++ кекать, но там настолько лоу левел, что как-то и писать о таком не хочется ✨
Upd. путон плутон пихтон пайтон python
Сам я на этом сейчас и сфокусирован. Пытаюсь ещё задачки решать на codeforces'e и с C++ кекать, но там настолько лоу левел, что как-то и писать о таком не хочется ✨
Upd. путон плутон пихтон пайтон python
Python, интерпретаторы, байткод, .pyc, .pyo, .pyd, JIT и прочее
Заголовок сочный, но как и говорил, всё очень кратко.
Давайте для начала примем, что Python - это интерфейс. Просто существует определённый набор того, что и как должно происходить, как должно себя вести.
Только выбрав имплементацию интерфейса уже можно говорить что-то о компиляции, байткоде и т.д. По дефолту такой реализацией является CPython - он же официальный (от самих разработчиков), он же самый популярный. Его и выберем, а о других просто будем знать, чтобы при необходимости заюзать.
Есть машинный код, а есть байткод. Машинный код прекрасен тем, что позволяет напрямую выполнять инструкции процессором. Байткод - некий промежуточный язык, понятный только виртуальной машине, которая и выполняет инструкции. Фишка машинного кода в том, что он дико быстрый, а байткода - возможность работать на разных платформах благодаря тому, что виртуальную машину можно написать для разных ОС и запускать один и тот же код везде. Так же байткод является более защищенным по очевидным причинам.
Дык вот CPython компилирует наш код в байткод. А потом выполняет его на своей виртуальной машине.
Собсна тоже самое и делает Java. У неё есть своя JVM, но почему-то она намного быстрее Python'a. Дело во многих вещах, но пока я затрону одно - JIT.
JIT - компиляция на лету. Фича в том, что у нас есть байткод, но было бы классно ещё и машинный местами использовать, чтобы ускорить выполнение. Этим и занимается Just in Time компиляция. Какие-то жирные куски, если есть возможность, она оптимайзит, компилирует в машинный код. Не всё так радужно, конечно. Ибо компиляция занимает время, но если выполнение и правда ускорится в разы, то это оправдано.
У JVM JIT есть, у CPython - нет. Обусловлено это тем, что CPython пытается быть всем и для всех. Из-за JIT программы долго запускаются. Если написать скрипт для выполнения в консоле, то нужен ли нам долгий запуск? Но CPython всего-лишь одна реализация интерфейса! И если мы точно знаем, что у нас, например, веб-приложение и мы запускаемся очень редко, а потом всё работаем и работаем - было бы классо иметь JIT и он у нас есть! В другой реализации - PyPy!
Upd. Для JIT есть еще Numba. Кста, забыл упомянуть, что CPython позволяет прикрутить к себе JIT.
Сухой список реализаций Python'a:
- PyPy - написан на RPython, использует JIT, отлично совместим с CPython (а это позволяет запускать Django, Flask и другие проекты без каких-либо изменений).
- Jython - компилирует наш python код в байткод для JVM (Java).
- IronPython - C#.
- Brython - JavaScript.
- RubyPython - Ruby.
и т.д. и т.п.
Upd. Ой как же я забыл про Cython, который трында бустит код в связи с второй траблой плутона - динамической типизацией.
Вернёмся к CPython. Он правда компилирует. Результатом компиляции являются .pyc файлы, который вы можете встречать после запуска своих приложений. Хочу отметить, что данные файлы появляются только у модулей. Когда вы импортируете какой-либо другой файл, только в этом случае его байткод будет сохранён в файл! Когда вы устанавливаете пакеты, через setup.py там, например, то при установке весь пакет компилируется и рядом с оригинальными .py файлами появляются скомпилированные .pyc!
Нужда в перекомпиляции определяется по множеству критериев, но есть один основной - дата изменения файла. Если .py изменён раньше, чем создан .pyc, то будет использовал скопилированный байткод. Ну тут вылезают рофлы с таймзоной и т.д. Да и вообще, это "компиляция" бустит только скорость запуска.
С .pyc разобрались, переходим к .pyo. Данные файлы - это тоже самое, что и .pyc, только без относительного мусора. Фишка в том, что будут вырезаны инструкции необходимые, например, для дебага. Или убраны все docstrings. Для получения таких файлов необходимо запустить интерпритатор с аргом -O для первого случая и -OO для второго.
.pyd - всё ещё проще. Доступно только для шиндовса и знаете что это? Обычные DLL'ки! Да, конечно у вас в коде тогда должен быть метод, для точки входа и бла-бла, но по сути просто ддлка с парочкой отличий.
Заголовок сочный, но как и говорил, всё очень кратко.
Давайте для начала примем, что Python - это интерфейс. Просто существует определённый набор того, что и как должно происходить, как должно себя вести.
Только выбрав имплементацию интерфейса уже можно говорить что-то о компиляции, байткоде и т.д. По дефолту такой реализацией является CPython - он же официальный (от самих разработчиков), он же самый популярный. Его и выберем, а о других просто будем знать, чтобы при необходимости заюзать.
Есть машинный код, а есть байткод. Машинный код прекрасен тем, что позволяет напрямую выполнять инструкции процессором. Байткод - некий промежуточный язык, понятный только виртуальной машине, которая и выполняет инструкции. Фишка машинного кода в том, что он дико быстрый, а байткода - возможность работать на разных платформах благодаря тому, что виртуальную машину можно написать для разных ОС и запускать один и тот же код везде. Так же байткод является более защищенным по очевидным причинам.
Дык вот CPython компилирует наш код в байткод. А потом выполняет его на своей виртуальной машине.
Собсна тоже самое и делает Java. У неё есть своя JVM, но почему-то она намного быстрее Python'a. Дело во многих вещах, но пока я затрону одно - JIT.
JIT - компиляция на лету. Фича в том, что у нас есть байткод, но было бы классно ещё и машинный местами использовать, чтобы ускорить выполнение. Этим и занимается Just in Time компиляция. Какие-то жирные куски, если есть возможность, она оптимайзит, компилирует в машинный код. Не всё так радужно, конечно. Ибо компиляция занимает время, но если выполнение и правда ускорится в разы, то это оправдано.
У JVM JIT есть, у CPython - нет. Обусловлено это тем, что CPython пытается быть всем и для всех. Из-за JIT программы долго запускаются. Если написать скрипт для выполнения в консоле, то нужен ли нам долгий запуск? Но CPython всего-лишь одна реализация интерфейса! И если мы точно знаем, что у нас, например, веб-приложение и мы запускаемся очень редко, а потом всё работаем и работаем - было бы классо иметь JIT и он у нас есть! В другой реализации - PyPy!
Upd. Для JIT есть еще Numba. Кста, забыл упомянуть, что CPython позволяет прикрутить к себе JIT.
Сухой список реализаций Python'a:
- PyPy - написан на RPython, использует JIT, отлично совместим с CPython (а это позволяет запускать Django, Flask и другие проекты без каких-либо изменений).
- Jython - компилирует наш python код в байткод для JVM (Java).
- IronPython - C#.
- Brython - JavaScript.
- RubyPython - Ruby.
и т.д. и т.п.
Upd. Ой как же я забыл про Cython, который трында бустит код в связи с второй траблой плутона - динамической типизацией.
Вернёмся к CPython. Он правда компилирует. Результатом компиляции являются .pyc файлы, который вы можете встречать после запуска своих приложений. Хочу отметить, что данные файлы появляются только у модулей. Когда вы импортируете какой-либо другой файл, только в этом случае его байткод будет сохранён в файл! Когда вы устанавливаете пакеты, через setup.py там, например, то при установке весь пакет компилируется и рядом с оригинальными .py файлами появляются скомпилированные .pyc!
Нужда в перекомпиляции определяется по множеству критериев, но есть один основной - дата изменения файла. Если .py изменён раньше, чем создан .pyc, то будет использовал скопилированный байткод. Ну тут вылезают рофлы с таймзоной и т.д. Да и вообще, это "компиляция" бустит только скорость запуска.
С .pyc разобрались, переходим к .pyo. Данные файлы - это тоже самое, что и .pyc, только без относительного мусора. Фишка в том, что будут вырезаны инструкции необходимые, например, для дебага. Или убраны все docstrings. Для получения таких файлов необходимо запустить интерпритатор с аргом -O для первого случая и -OO для второго.
.pyd - всё ещё проще. Доступно только для шиндовса и знаете что это? Обычные DLL'ки! Да, конечно у вас в коде тогда должен быть метод, для точки входа и бла-бла, но по сути просто ддлка с парочкой отличий.
Отличное начало дня. Захожу в метро, подготовил карту уже для оплаты. Смотрю - зелёный горит на крайнем. Думаю фили мне, пойду через него не прикладывая карту (явно забагался, ибо зелёный горит определённое время). Ну и чё вы думаете? Прошел как царь. Ещё обернулся на него с удивлением и такой - ок, пасиба. Всё это очень интересно (нет), но читать статьи на хабре как люди ревёрсят эти терминалы и карты подделывают на безлимитные поездки ещё интереснее. Правда, в большинстве случаев, нужен сам этот терминал. Собсна в одной статье на хабре человеку с этим повезло. Простите, извините, ссылку не нашёл. Про подделку в Нижнем Новгороде не то.
Короч сегодняшний пост про пухтон конечно же будет про типизацию ✨
Короч сегодняшний пост про пухтон конечно же будет про типизацию ✨
Вода про типизацию и не надо хейтить пухтон за динамическую (или надо)
Чтобы разобраться чё там у Python'a, надо понять что есть вообще, чем отличается и т.д. и т.п.
Тип - множество значений и операций над этими значениями (пасиба вики).
Как знает большинство, бывает статическая и динамическай типизация. А чё-нить ещё знает большинство или только зная это уже хейтит?
Статическая/динамическая, сильная/слабая, явная/неявная.
Максимально быстро по каждому, а то прошлый пост большим вышел.
Статическая - типы устанавливаются на этапе компиляции, динамическая - в рантайме.
Сильная - отсутствие автоматических кастов в другой тип (неявных преборазований). Слабая - наличие таковых.
Явная - указываем типы везде ручками. Неявная - компилятор/интерпретатор занимается этим сам.
Теперь мы знаем че есть и давайте сравним JavaScript и Python.
JavaScript - динамическая слабая неявная.
Python - динамическая сильная неявная.
Вот как раз в сильной типизации вся сила, как бы это не звучало. Python старается предупреждать о всякой диче, что может произойти, например, по ошибке программиста. Он не даст вам сложить str с int, а вот JavaScript сделает всё возможное, чтобы ваше желание было исполнено.
Давайте глянем на плюсы и минусы между типизацией Python'a и полной противоположностью - статической слабой явной (не знаю есть ли ЯП с такой).
Плюсы:
- можем мешать типы данных в пределах одной коллекции;
- пишем универсальные методы (алги) готовые работать с чем угодно (пока перегрузкам и т.д.);
- благодоря сильной типизации имеем надеждность, понимание что вообще происходит и отсутствие замедлений всякими кастами;
- к плюсам неявности сокращение записи что ль.
Минусы:
- теряем скорость;
- теряем подсказки IDE и подсказки по поводу ошибок (привет Python аннотации которые это фиксят);
- местами теряем краткость записи из-за необходимости кастовать руками;
- теряем сигнатуры методов, посмотрев на которые можно понять что передавать (аннотации вновь спасают);
По поводу неявных преобразований в Python'e, то можно смело сказать, что они есть. Дело в том, что тут нет одной стороны. Типо кастим хоть куда, только бы сложить (JS), или не кастим вообще и всегда кидаем исключение. Python старается быть умным. Если есть два типа и операция сложения между ними вполне логична, ясна и понятна - давай сделаем это.
Примером может быть int + float:
Что мне дико не нравится, так это потеря данных при неявных кастах. Но всё нужно уметь варить (в JS я пока просто использую
В прошлом посте я рассказал про то, что одна из причин медленности Python'a - отсутствие JIT'a. А вторая - динамическая типизация, НО, не конкретно она сама, а то, как архитектура языка усложняет оптимизацию! И всё по старой причине - Python пытается быть всем и вся. Он дико гибок, за счёт этого оптимайзить сложно, а проверка типов осуществляется при каждом доступе к переменной!
Говоря про реализации Python'a я упомянул Cython, но не сказал что это. А всё очень просто. Это Python с статической типизацией.
Прям в тему поста сегодня пикча в инсте попалась
Чтобы разобраться чё там у Python'a, надо понять что есть вообще, чем отличается и т.д. и т.п.
Тип - множество значений и операций над этими значениями (пасиба вики).
Как знает большинство, бывает статическая и динамическай типизация. А чё-нить ещё знает большинство или только зная это уже хейтит?
Статическая/динамическая, сильная/слабая, явная/неявная.
Максимально быстро по каждому, а то прошлый пост большим вышел.
Статическая - типы устанавливаются на этапе компиляции, динамическая - в рантайме.
Сильная - отсутствие автоматических кастов в другой тип (неявных преборазований). Слабая - наличие таковых.
Явная - указываем типы везде ручками. Неявная - компилятор/интерпретатор занимается этим сам.
Теперь мы знаем че есть и давайте сравним JavaScript и Python.
JavaScript - динамическая слабая неявная.
Python - динамическая сильная неявная.
Вот как раз в сильной типизации вся сила, как бы это не звучало. Python старается предупреждать о всякой диче, что может произойти, например, по ошибке программиста. Он не даст вам сложить str с int, а вот JavaScript сделает всё возможное, чтобы ваше желание было исполнено.
Давайте глянем на плюсы и минусы между типизацией Python'a и полной противоположностью - статической слабой явной (не знаю есть ли ЯП с такой).
Плюсы:
- можем мешать типы данных в пределах одной коллекции;
- пишем универсальные методы (алги) готовые работать с чем угодно (пока перегрузкам и т.д.);
- благодоря сильной типизации имеем надеждность, понимание что вообще происходит и отсутствие замедлений всякими кастами;
- к плюсам неявности сокращение записи что ль.
Минусы:
- теряем скорость;
- теряем подсказки IDE и подсказки по поводу ошибок (привет Python аннотации которые это фиксят);
- местами теряем краткость записи из-за необходимости кастовать руками;
- теряем сигнатуры методов, посмотрев на которые можно понять что передавать (аннотации вновь спасают);
По поводу неявных преобразований в Python'e, то можно смело сказать, что они есть. Дело в том, что тут нет одной стороны. Типо кастим хоть куда, только бы сложить (JS), или не кастим вообще и всегда кидаем исключение. Python старается быть умным. Если есть два типа и операция сложения между ними вполне логична, ясна и понятна - давай сделаем это.
Примером может быть int + float:
1 + 1.1 = 2.1
А пример исключения: "daa" + 1
(в JS выполнится, будет строка "daa1")Что мне дико не нравится, так это потеря данных при неявных кастах. Но всё нужно уметь варить (в JS я пока просто использую
===
и !==
на всякий)! Тут же и про то, что лучше начинать изучать прогу не с динамического языка (ибо не будет понимания). Всё относительно. Сам я начал свой путь с пасика в 5 классе, спустя несколько лет ушёл на динамическую типизацию слабую и даже не догадывался про тройное равно. Сейчас не ощущаю каких-либо проблем в понимании.В прошлом посте я рассказал про то, что одна из причин медленности Python'a - отсутствие JIT'a. А вторая - динамическая типизация, НО, не конкретно она сама, а то, как архитектура языка усложняет оптимизацию! И всё по старой причине - Python пытается быть всем и вся. Он дико гибок, за счёт этого оптимайзить сложно, а проверка типов осуществляется при каждом доступе к переменной!
Говоря про реализации Python'a я упомянул Cython, но не сказал что это. А всё очень просто. Это Python с статической типизацией.
Прям в тему поста сегодня пикча в инсте попалась
Marshal's channel
Мне отказали 4 команды из четырех при рефке, даже на собес не позвали. И на стажку даже на собес не позвали, если там отлетел по опыту, то тут по таскам. Ы, минус яндух, вариантов больше нет, ладно, го дальше
This media is not supported in your browser
VIEW IN TELEGRAM
Кто-нибудь да поймет 🙃
https://github.com/zxystd/AppleIntelWifiAdapter/commits/feature-rewrite-all
Сморите шо кони творят, интеловскую фавлю заводят на макоси для хакинтошников. Ето ведь мечта, скока лет пердим покупая броадкомы.
Ща какой-нить изи пост про пухтон набросаю
Сморите шо кони творят, интеловскую фавлю заводят на макоси для хакинтошников. Ето ведь мечта, скока лет пердим покупая броадкомы.
Ща какой-нить изи пост про пухтон набросаю
GitHub
zxystd/AppleIntelWifiAdapter
苹果IO80211Controller调用. Contribute to zxystd/AppleIntelWifiAdapter development by creating an account on GitHub.
Встроенные типы в Python и интересные моменты
Я там выше knowledge map по Python’у скидывал. Посмотрев чуть подробнее понял, что это максимум ориентир тем. Про дикую годноту забираю слова обратно, ошибся.
Иногда на собесах просят просто перечислить встроенные типы. Из дефолт пакетов тоже любят спросить.
int, float, bool, str. Очень интересно, ага, да. Или рил интересно?
Целые числа
У интов есть методы, ведь у нас тут всё классы. Поэтому
Числа с плавающей точкой
Класс float - имплементация абстрактного класса Real. Тоже есть методы, например, такой классный как
Если в комплексном нам нужна j в конце для обозначения, то тут точка.
Комплексные числа
Модуль math при
Типы последовательностей: list, tuple, range
List мутабельный, можно объявить как []. Доступен конструктор list(), можно использовать списковое включение (о нем потом).
Tuples - кортежи не мутируются. Объявлятся как (), конструктор tuples(). Есть один маленький рофел, который не всем заходит.
a = 1,
type(a) - tuple
type(1,) - int
Т.е. кортеж не обязательно должен объявляться через круглые скобки. Мы бывает юзаем кортежи в возврате методов и там просто перечисляем что вернуть через запятую. Понятное дело, такое работает не везде. Если мы хотим передать кортеж в арги, то обязательно используем скобки:
Ranges - не мутируются. Исключительно конструктором передаём минимум один арг - stop.
Строки
Без лишних комментариев. Объявляем ‘tak’, “tak”, ‘’’tak’’’ i “””tak”””
Для строк у нас есть еще обозначения перед ними:
r - raw string - игнорим бэкслеш
b - бинарные
f - строки для форматирования
Типы бинарных последовательностей
bytes(), bytearray(), memoryview()
Для всех типов-последовтаельностей доступны такие фичи как in, например (a in b, где b - последовательность)
Типы множеств
Коллекция без порядка. Недопустимы дубликаты в элементах.
Set - мутабельный, frozenset - нет (можно получить хэш).
Тип словарь
dict() - мутабельный.
.keys() - ключи, .values() - значения, .items() пары (ключ, значение)
Да, есть еще встроенные типы, но вверху основные представители без уж ну самых скучных.
А теперь прост список типов из пакетов, ы:
datetime: timedelta, date, datetime, time, timezone, tzinfo.
collections: Counter, deque, defaultdict, OrderedDict, namedtuple
И ещё много-много всего, но мы ведь хотим успеть и на другие вопросы на собесе ответить. Кому не лень - кидайте в чатик ещё придерживаясь формата)
Я там выше knowledge map по Python’у скидывал. Посмотрев чуть подробнее понял, что это максимум ориентир тем. Про дикую годноту забираю слова обратно, ошибся.
Иногда на собесах просят просто перечислить встроенные типы. Из дефолт пакетов тоже любят спросить.
int, float, bool, str. Очень интересно, ага, да. Или рил интересно?
Целые числа
У интов есть методы, ведь у нас тут всё классы. Поэтому
(1).bit_lenght()
, а ещё .(to/from)_bytes
. Больше интересного нет.Числа с плавающей точкой
Класс float - имплементация абстрактного класса Real. Тоже есть методы, например, такой классный как
.is_integer()
и .hex()
Если в комплексном нам нужна j в конце для обозначения, то тут точка.
a = 1.
b = 1.1
Комплексные числа
a = 27j
- тип complex (даа, j в конце).Модуль math при
sqrt(-1)
выдаст исключение, а модуль cmath - комплексное число.Типы последовательностей: list, tuple, range
List мутабельный, можно объявить как []. Доступен конструктор list(), можно использовать списковое включение (о нем потом).
Tuples - кортежи не мутируются. Объявлятся как (), конструктор tuples(). Есть один маленький рофел, который не всем заходит.
a = 1,
type(a) - tuple
type(1,) - int
Т.е. кортеж не обязательно должен объявляться через круглые скобки. Мы бывает юзаем кортежи в возврате методов и там просто перечисляем что вернуть через запятую. Понятное дело, такое работает не везде. Если мы хотим передать кортеж в арги, то обязательно используем скобки:
foo((1, ))
Ranges - не мутируются. Исключительно конструктором передаём минимум один арг - stop.
range(start, stop, step)
. В памяти только три арга и хранит.Строки
Без лишних комментариев. Объявляем ‘tak’, “tak”, ‘’’tak’’’ i “””tak”””
Для строк у нас есть еще обозначения перед ними:
r - raw string - игнорим бэкслеш
b - бинарные
f - строки для форматирования
Типы бинарных последовательностей
bytes(), bytearray(), memoryview()
Для всех типов-последовтаельностей доступны такие фичи как in, например (a in b, где b - последовательность)
Типы множеств
Коллекция без порядка. Недопустимы дубликаты в элементах.
Set - мутабельный, frozenset - нет (можно получить хэш).
Тип словарь
dict() - мутабельный.
.keys() - ключи, .values() - значения, .items() пары (ключ, значение)
Да, есть еще встроенные типы, но вверху основные представители без уж ну самых скучных.
А теперь прост список типов из пакетов, ы:
datetime: timedelta, date, datetime, time, timezone, tzinfo.
collections: Counter, deque, defaultdict, OrderedDict, namedtuple
И ещё много-много всего, но мы ведь хотим успеть и на другие вопросы на собесе ответить. Кому не лень - кидайте в чатик ещё придерживаясь формата)
Как устроен словарь (dict) в Python
Если с объяснением того, что такое дикт и как его юзать у нас проблем не возникает, то вот ответить как они устроены в Python, а при правильном ответе получить следующий: “А как решаются коллизии?”, то уже ответить проблематичнее.
Отвечаю сразу на первый вопрос - в Python’e ассоциативный массив реализован с помощью хеш-таблицы (для заметки, в C++ красно-чёрные деревья).
В основе всего лежит хеш-функция. И вот многие говорят, что хорошая хеш-функция эта то, что дает более рандомный ответ, но разравы путона так не считают и их хеша схожи, даже для разных строк. Этим своством они пользуются для оптимизации, но об этом ниже.
Уж не будем про то, что такое хеш, просто строка байт, полученная от какого-то алгоса, которому скормили какие-то входные данные. Для одинаковых данных будет один и тот же хеш.
В общем есть пару статей на эту тему, но там всё устарело, ибо с Python3.6 были некоторые оптимайзы по памяти. То, как представлен словарь. Подходы, алги и т.д. не меняли. На данный момент PyDictObject представляет из себя структуру из:
- PyObject_HEAD:
- ma_used;
- ma_version_tag;
- *ma_keys;
- **ma_values;
ma_used - кол-во айтемов в словарею ma_version_tag - просто глобальное уникальное значение, которое меняется при каждом изменении словаря.
Дальше объяснить будет чуть сложнее, ибо сейчас вкину то, о чем расскажу ниже.
ma_keys - PyDictKeysObject который там в конце концов сводится к PyDictKeyEntry (пропущен жирный пласт с количеством юзабельных и использованных entries и т.д., сорри), а он, в свою очередь, состоит из:
- me_hash;
- *me_key;
- *me_value.
С этой сттруктурой всё понято, дык вот фича в том, что ma_keys конкретно для ключей и значений используется только тогда, когда таблица не является разорванной/разделенной (splitted короче). Когда же таблица “combined”, то ключи используются из me_key, а значения из me_value!
Задетектить сплитед она или комбаин легко. Если
Имеем хоть какое-то представление теперь о славорях в реализации CPython, идем дальше к самому вкусному.
В каждом слоте хеш-таблицы может храниться только один объект (хеш, ключ, значение).
Конечно же имеются коллизии (когда у двух разных объектов одинаковый хеш) и это нормально, такое надо уметь решать.
Есть несколько алгоритмов разрешать их, но в нашем случае - это открытая адресация. Есть ещё алгоритм через цеопчки (храним лист), но он проигрывает по памяти из-за хранение указателей на элементы в списке, но у него конечно есть плюсы. Речь не о чем, “Python” сделал свой выбор.
Алгоритм открытой адресации очень прост. Мы берем хеш нашего ключа и делаем MOD <размер хеш-таблицы>. Таким образом получаем индекс для вставки нашего элемента. Что же происходит, когда ячейка уже занята? Просто берем и смотрим в следующую, да-да, тупо выходит следующее:
Когда нам необходимо найти что-то, то делаем тоже самое, только попав на какую-то ячейку проверяем её по хешу и ключу, если мы попали не туда - делаем +1 и смотрим дальше.
Хотим удалить что-то? Затираем элемент, но ставим маркер на эту ячейку, если за ней есть другие элементы, если нет - просто удаляем.
И вот как раз когда мы удаляем(затираем), появляются несколько последовательность, между которыми может стоять маркер. Это и есть splitted хэш-таблица!
Маркер нужен для того, чтобы не прекратить наш линейный поиск ячейки с нужным нам значением тогда, когда мы дойдем до пустой ячейки (ибо дальше есть другие).
Понятное дело, что чем больше вот таких пустых мест, тем дольше мы будем всё искать и искать, куда же мы там сохранили. Для этого есть пересоздание словаря. Чет тип фрагментации что ль. Есть критическое значение маркеров, при котором создается новый словарь из старых значением, но без “пробелов” между ячейками.
Entry в словаре (слот) может быть в одном из 4 состояний: unused, active, dummy и pending. Подробнее о каждом сможете почитать сами, снизу линк.
НА САМОМ ДЕЛЕ НЕ ВСË ТАК ПРОСТО
Если с объяснением того, что такое дикт и как его юзать у нас проблем не возникает, то вот ответить как они устроены в Python, а при правильном ответе получить следующий: “А как решаются коллизии?”, то уже ответить проблематичнее.
Отвечаю сразу на первый вопрос - в Python’e ассоциативный массив реализован с помощью хеш-таблицы (для заметки, в C++ красно-чёрные деревья).
В основе всего лежит хеш-функция. И вот многие говорят, что хорошая хеш-функция эта то, что дает более рандомный ответ, но разравы путона так не считают и их хеша схожи, даже для разных строк. Этим своством они пользуются для оптимизации, но об этом ниже.
Уж не будем про то, что такое хеш, просто строка байт, полученная от какого-то алгоса, которому скормили какие-то входные данные. Для одинаковых данных будет один и тот же хеш.
В общем есть пару статей на эту тему, но там всё устарело, ибо с Python3.6 были некоторые оптимайзы по памяти. То, как представлен словарь. Подходы, алги и т.д. не меняли. На данный момент PyDictObject представляет из себя структуру из:
- PyObject_HEAD:
- ma_used;
- ma_version_tag;
- *ma_keys;
- **ma_values;
ma_used - кол-во айтемов в словарею ma_version_tag - просто глобальное уникальное значение, которое меняется при каждом изменении словаря.
Дальше объяснить будет чуть сложнее, ибо сейчас вкину то, о чем расскажу ниже.
ma_keys - PyDictKeysObject который там в конце концов сводится к PyDictKeyEntry (пропущен жирный пласт с количеством юзабельных и использованных entries и т.д., сорри), а он, в свою очередь, состоит из:
- me_hash;
- *me_key;
- *me_value.
С этой сттруктурой всё понято, дык вот фича в том, что ma_keys конкретно для ключей и значений используется только тогда, когда таблица не является разорванной/разделенной (splitted короче). Когда же таблица “combined”, то ключи используются из me_key, а значения из me_value!
Задетектить сплитед она или комбаин легко. Если
me_value is Null
- combinedИмеем хоть какое-то представление теперь о славорях в реализации CPython, идем дальше к самому вкусному.
В каждом слоте хеш-таблицы может храниться только один объект (хеш, ключ, значение).
Конечно же имеются коллизии (когда у двух разных объектов одинаковый хеш) и это нормально, такое надо уметь решать.
Есть несколько алгоритмов разрешать их, но в нашем случае - это открытая адресация. Есть ещё алгоритм через цеопчки (храним лист), но он проигрывает по памяти из-за хранение указателей на элементы в списке, но у него конечно есть плюсы. Речь не о чем, “Python” сделал свой выбор.
Алгоритм открытой адресации очень прост. Мы берем хеш нашего ключа и делаем MOD <размер хеш-таблицы>. Таким образом получаем индекс для вставки нашего элемента. Что же происходит, когда ячейка уже занята? Просто берем и смотрим в следующую, да-да, тупо выходит следующее:
hash(k) % TABLE_SIZE + i
, где i, какой-нибудь счетчик, пока не дойдем до свободной ячейки!Когда нам необходимо найти что-то, то делаем тоже самое, только попав на какую-то ячейку проверяем её по хешу и ключу, если мы попали не туда - делаем +1 и смотрим дальше.
Хотим удалить что-то? Затираем элемент, но ставим маркер на эту ячейку, если за ней есть другие элементы, если нет - просто удаляем.
И вот как раз когда мы удаляем(затираем), появляются несколько последовательность, между которыми может стоять маркер. Это и есть splitted хэш-таблица!
Маркер нужен для того, чтобы не прекратить наш линейный поиск ячейки с нужным нам значением тогда, когда мы дойдем до пустой ячейки (ибо дальше есть другие).
Понятное дело, что чем больше вот таких пустых мест, тем дольше мы будем всё искать и искать, куда же мы там сохранили. Для этого есть пересоздание словаря. Чет тип фрагментации что ль. Есть критическое значение маркеров, при котором создается новый словарь из старых значением, но без “пробелов” между ячейками.
Entry в словаре (слот) может быть в одном из 4 состояний: unused, active, dummy и pending. Подробнее о каждом сможете почитать сами, снизу линк.
НА САМОМ ДЕЛЕ НЕ ВСË ТАК ПРОСТО
Я рассказал про банальную открытую адресацию, но в Python’e используют как раз то, что я упомянул выше - схожесть хешей. В связи с этим поиск нужной ячейки получается совсем не просто +1, а есть определенный шаг, с которым мы ходим. Есть linear probing (наш +1 каждый раз), а есть double probing. Фича второго в том, что мы двигаемся не на +1, а на хэш, но уже второй функции от того же k.
Я бы не сказал, что в Python’e используется двойное хеширование, у них своё. Шаг вычисляется так:
Всё это дико интересно конечно, но в то, как это работает я особо не вникал, хотя они всё подробно расписали в доке к методу (линк снизу).
Кста, есть фактик. Каждый словарь инициализируется с 8 слотами, что позволяет сохранять 5 элементов. Сделано это для того, что в большинстве мест, в самом CPython очень часто используются словари всего для 2-3 элементов и чтобы не использовать больше памяти, чем надо, поступили вот так. И да, насколько помню, у нас что в листах, что тут, всегда выделено больше памяти и больше доступно ячеек, чем есть на самом деле. То, что у вас
Чтобы избежать замедления поиска в хеш-таблице она ресайзиться при заполнении на две трети.
Собсна у меня всё, было интересно посмотреть на исходники CPython’a. Будет что рассказать на собесах, надеюсь и Вам тоже. Я кста не перечитываю что написал, да-да.
Кста, забыл уточнить, что если в открытой адресации вот MOD вроде как используют и даже в доке об этом пишут, то на деле в коде вместо % стоит &:
(объясните плиз, кто может)
Вот про MOD из доки: https://github.com/python/cpython/blob/master/Objects/dictobject.c#L741
Обещанные ссылки:
- https://github.com/python/cpython/blob/master/Objects/dictobject.c#L52 - от сюда про сплитед и компаинед таблицу, а так же про состояние ячеек.
- https://github.com/python/cpython/blob/master/Objects/dictobject.c#L135 - а вот от сюда жирная дока по тому, как же работает их PERTURB_SHIFT (эт который не тупое +1)
- https://github.com/python/cpython/blob/master/Objects/dict-common.h - тут PyDictKeyEntry и промежуточная структура, о которой я ничего не рассказал.
- https://github.com/python/cpython/blob/master/Include/cpython/dictobject.h - сткруктура самого PyDictObject
- https://neerc.ifmo.ru/wiki/index.php?title=Разрешение_коллизий - про разрешение коллизий
- https://mail.python.org/pipermail/python-dev/2012-December/123028.html - про изменение структуры с Python3.6 для экономии памяти.
Поправьте меня, если где-то был не прав ✨
Upd. Ору, в одно сообщение не влезло. Когда сказал, что будут краткие и поверхностные посты, а они всё равно длинные. Вы понимаете сколько писать на эту тему можно? :D
Я бы не сказал, что в Python’e используется двойное хеширование, у них своё. Шаг вычисляется так:
j = (5*j) + 1 + perturb;
Всё это дико интересно конечно, но в то, как это работает я особо не вникал, хотя они всё подробно расписали в доке к методу (линк снизу).
Кста, есть фактик. Каждый словарь инициализируется с 8 слотами, что позволяет сохранять 5 элементов. Сделано это для того, что в большинстве мест, в самом CPython очень часто используются словари всего для 2-3 элементов и чтобы не использовать больше памяти, чем надо, поступили вот так. И да, насколько помню, у нас что в листах, что тут, всегда выделено больше памяти и больше доступно ячеек, чем есть на самом деле. То, что у вас
len([1,2,3])
выдает 3, не значит, что там на самом деле столько ячеек. Связано это с тем, что выделять по 1 ячейке при каждом append’e слишком дорого по времени, поэтому выделяют всегда с запасом для следующих вставок. Чтобы избежать замедления поиска в хеш-таблице она ресайзиться при заполнении на две трети.
Собсна у меня всё, было интересно посмотреть на исходники CPython’a. Будет что рассказать на собесах, надеюсь и Вам тоже. Я кста не перечитываю что написал, да-да.
Кста, забыл уточнить, что если в открытой адресации вот MOD вроде как используют и даже в доке об этом пишут, то на деле в коде вместо % стоит &:
size_t i = hash & mask;
i = mask & (i*5 + perturb + 1);
(объясните плиз, кто может)
Вот про MOD из доки: https://github.com/python/cpython/blob/master/Objects/dictobject.c#L741
Обещанные ссылки:
- https://github.com/python/cpython/blob/master/Objects/dictobject.c#L52 - от сюда про сплитед и компаинед таблицу, а так же про состояние ячеек.
- https://github.com/python/cpython/blob/master/Objects/dictobject.c#L135 - а вот от сюда жирная дока по тому, как же работает их PERTURB_SHIFT (эт который не тупое +1)
- https://github.com/python/cpython/blob/master/Objects/dict-common.h - тут PyDictKeyEntry и промежуточная структура, о которой я ничего не рассказал.
- https://github.com/python/cpython/blob/master/Include/cpython/dictobject.h - сткруктура самого PyDictObject
- https://neerc.ifmo.ru/wiki/index.php?title=Разрешение_коллизий - про разрешение коллизий
- https://mail.python.org/pipermail/python-dev/2012-December/123028.html - про изменение структуры с Python3.6 для экономии памяти.
Поправьте меня, если где-то был не прав ✨
Upd. Ору, в одно сообщение не влезло. Когда сказал, что будут краткие и поверхностные посты, а они всё равно длинные. Вы понимаете сколько писать на эту тему можно? :D
Проблема с постами решена!
Посты слишком длинные, в тележке стало тесно и неудобно читать в целом. С телеги уходить никуда конечно не будем, поэтому нужен Instant View. Я хотел реанимировать свой сайт, но так подумал, что пилить велик нет сил и желания, а я в последнее время всё чаще стал слышать про Яндекс.Дзен. И это то, что надо! Конечно, есть один маленький минус... Там нельзя красиво форматнуть код, к сожалению, но в любом случае, все последние посты-статьи по Python'у уже там!
Чтобы задать уникальную ссылку надо много просмотров, поэтому предлагаю вот такое решение: https://zen.marshal.by ✨
Впредь все новые длинные посты будут публиковаться там (возможно, некоторые еще туда перенесу), а через канал можно будет почитать в IV.
Посты без превью выглядят в блоках ужасно, если кто-то может помочь сделать фон для каждого поста, у которого нет изображений внутри - помогите, пожалуйста)
Upd. Шот походу придётся переехать ещё раз, но дзен можно засейвить будет, генеря RSS feed, в общем есть чё покодить маленько 🌚
Посты слишком длинные, в тележке стало тесно и неудобно читать в целом. С телеги уходить никуда конечно не будем, поэтому нужен Instant View. Я хотел реанимировать свой сайт, но так подумал, что пилить велик нет сил и желания, а я в последнее время всё чаще стал слышать про Яндекс.Дзен. И это то, что надо! Конечно, есть один маленький минус... Там нельзя красиво форматнуть код, к сожалению, но в любом случае, все последние посты-статьи по Python'у уже там!
Чтобы задать уникальную ссылку надо много просмотров, поэтому предлагаю вот такое решение: https://zen.marshal.by ✨
Впредь все новые длинные посты будут публиковаться там (возможно, некоторые еще туда перенесу), а через канал можно будет почитать в IV.
Посты без превью выглядят в блоках ужасно, если кто-то может помочь сделать фон для каждого поста, у которого нет изображений внутри - помогите, пожалуйста)
Upd. Шот походу придётся переехать ещё раз, но дзен можно засейвить будет, генеря RSS feed, в общем есть чё покодить маленько 🌚
Zen
Marshal`s channel | Яндекс Дзен
Ведя свой Telegram канал (блог IT парня), в котором делюсь различными ссылками, вещами что нахожу, просто моментами из своей жизни - запустил серию постов про Python. Решил пройтись по нему с нуля, затронуть интересные моменты, разобрать вопросы с собесов.…
Ору, изи значок
https://www.instagram.com/p/B9Rjf81q-CM/?igshid=opap1fkmus8k
https://www.instagram.com/p/B9Rjf81q-CM/?igshid=opap1fkmus8k
GIL (Global Interpreter Lock) в Python
Я не успел переписать свой сайт на Headless CMS к новому посту, эх. Закончу - обязательно буду постить туда, а оно уже будет дублировать контент на другие платформы. Там же и IV в телегу будет. Сейчас же довольствуемся яндекс дзеном 😔
Как закончу пилить сайтецкий и все эти автопубликации - обязательно напишу об этом и поделюсь со всем с Вами ✨
Над ещё в каждом сообщение на всякий напоминать, что я не читаю в конце то, что написал 😝
Я не успел переписать свой сайт на Headless CMS к новому посту, эх. Закончу - обязательно буду постить туда, а оно уже будет дублировать контент на другие платформы. Там же и IV в телегу будет. Сейчас же довольствуемся яндекс дзеном 😔
Как закончу пилить сайтецкий и все эти автопубликации - обязательно напишу об этом и поделюсь со всем с Вами ✨
Над ещё в каждом сообщение на всякий напоминать, что я не читаю в конце то, что написал 😝
Яндекс Дзен
GIL (Global Interpreter Lock) в Python
Изначально я хотел сразу начать отвечать на вопрос с собеса про память в Python, но поняв, что выйдет очень длинно, решил разбить на несколько постов. Сейчас поговорим про GIL, в следующих статьях про GC, закончим уже поверхностно про пуллы памяти, арены.…