Marshal's channel
846 subscribers
288 photos
46 videos
8 files
328 links
About me: @ilya_marshal
Download Telegram
Вода про типизацию и не надо хейтить пухтон за динамическую (или надо)

Чтобы разобраться чё там у 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 с статической типизацией.

Прям в тему поста сегодня пикча в инсте попалась
Мне отказали 4 команды из четырех при рефке, даже на собес не позвали. И на стажку даже на собес не позвали, если там отлетел по опыту, то тут по таскам. Ы, минус яндух, вариантов больше нет, ладно, го дальше
https://github.com/zxystd/AppleIntelWifiAdapter/commits/feature-rewrite-all

Сморите шо кони творят, интеловскую фавлю заводят на макоси для хакинтошников. Ето ведь мечта, скока лет пердим покупая броадкомы.


Ща какой-нить изи пост про пухтон набросаю
Встроенные типы в Python и интересные моменты

Я там выше 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!

Задетектить сплитед она или комбаин легко. Если 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 используется двойное хеширование, у них своё. Шаг вычисляется так:
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, в общем есть чё покодить маленько 🌚
Иронично
GIL (Global Interpreter Lock) в Python

Я не успел переписать свой сайт на Headless CMS к новому посту, эх. Закончу - обязательно буду постить туда, а оно уже будет дублировать контент на другие платформы. Там же и IV в телегу будет. Сейчас же довольствуемся яндекс дзеном 😔

Как закончу пилить сайтецкий и все эти автопубликации - обязательно напишу об этом и поделюсь со всем с Вами

Над ещё в каждом сообщение на всякий напоминать, что я не читаю в конце то, что написал 😝
Шота ор, заботливые какие 🤗 заботливее всех девушек, что там есть 🌚
Нужна помощь, иду на завод

Нет больше людей к которым я могу обратиться и времени тоже, последняя надежда

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

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

Сейчас я в поисках людей, которые могут мне хоть чем-то помочь. Идея есть: получить вызов, например, от ИП и якобы проходить практику у него (прикрыть пятую точку). Трудоустраивать меня сейчас не надо! Это только 1 августа, а до того времени я уже устроюсь куда-нибудь и перераспределюсь. Как запасной вариант начну выплачивать за обучение.

К сожалению, помочь мне могут только ИП и юр. лица Республики Беларусь.

Мой линкид
Мой сайт со всеми контактами
Гитхаб с примером кода
Статейки на хабре

Полное резюме предоставлю по запросу: @MarshalX

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

Буду благодарен за репост. Девушки, с наступающим!

P.S. Помочь могут любые ИП, вне зависимости от того, чем они занимаются. Вызов просто нужно сделать на должность "инженер-программист". Если это компания, то там должна быть соответствующая должность.
План-барабан.png
120.5 KB
Схороню для себя свою диагу.

Есть я, есть три пути (синий) по которым можно пойти (это без учёта махинаций с распредом в одно место, а работать в другом).

Цель - стать свободным и катиться на все 4 стороны (зеленый).

Много где теряю деньги, много где теряю время. С варианта в 28 лет до цели я вообще ору.

К сожалению, всё упирается в армию. Знал бы точно ответ по ней, всяких ветвей было куда меньше, ы

Вариант поступить в ВУЗ, прикроя жэпу от распреда и чуть шо уйти в академ, если армия, очень даже годный да и в вуз я чет хочу. Всегда можно потом слиться, да, займу чье-то место, но, увы, сос
Marshal's channel
План-барабан.png
У меня тут три пути, но был четвертый, в который я уже не верил - найти куда распределиться. Не верил я в него потому что сегодня последний день, когда можно получить именной вызов.

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

Честно говоря я не особо хотел туда идти, думал перенести на другой день даже, ибо его хотели поставить вечером, но перенесли в удобное для меня время. Не хотел я идти туда потому что знал, что меня сегодня распределят в жопу и на работу, в лучшем случае, выйду в мае.

Я пришел, мне позадавали вопросов, потом рассказали о компании и о проектах. Ребята не аутсорсят, это шик. У них свои классные проекты. Потом я рассказал про свою ситуацию с распредом, что сегодня последний день и фиг знает когда я смогу работать. Знаете что я услышал? “Рисковый парень”, “Можем запрыгнуть в последний вагон”. Да, они просто взяли и предложили сделать вызов в последний день.

Сегодня я забрал трудовую с прошлого места работы и сегодня же отдал на новое.

Моя история звучит просто как сказка . Как думаете, это правда?) @MarshalCh
Media is too big
VIEW IN TELEGRAM
Одно из лучших вложений в прилу из app store (2.49$). Потому что менеджить размер окна тачпадом фи, а на хоткеях топ. Для виндоидов тут и прилипалка окон есть.

Кто не юзает Magnet, тот или страдает, или просто не держит больше 1 окна и работает исключительно через десктопы. Сам я комбинирую это

Кста, попробовал я тайловый менеджер, аметист, нее, конечно по сравнению с i3 небо и земля. Не вписывается оно к этим вашим окошкам макосовским, ещё и багует с десктопами, когда не через хоткеи аметиста что-то делаешь. Да и выглядят не оч
Forwarded from INTERNET 9000
Антон Гладкобородов, основатель Coub, запустил необычное todo-приложение — эдакий эксель для списков.

(Он говорит, что это «не Трелло/Ноушн и это не таск менеджер», поэтому попробуйте сами, и расскажите, так ли это).

columns.me
Marshal's channel
Антон Гладкобородов, основатель Coub, запустил необычное todo-приложение — эдакий эксель для списков. (Он говорит, что это «не Трелло/Ноушн и это не таск менеджер», поэтому попробуйте сами, и расскажите, так ли это). columns.me
Самому мне больше трелло зашёл Quire. Эдакий список с вложеностью, возможностью маркать и асанить таски, делать периодические таски, добавлять описание на маркдауне и дискуссировать под каждой. Вот пример, когда я к конкурсу готовился (выдрал ссыль из статьи на хабре): https://quire.io/w/IT-Planet/

Ссыль походу всё, того. В общем тогда без примера попробуйте сами! Quire.io

Upd. открывается, но не на мобилках. Заходите с компа или качайте прилу на на телефон
Сколько я спал, что в директе инсты можно теперь сидеть через ПК без responsive design mode в тулзах баузера? 😳

Я уже подумал, что это благодаря недавнему Facebook Container’y (https://addons.mozilla.org/ru/firefox/addon/facebook-container/), но в приватной вкладке тоже есть директ

filter: blur(10px) топ кста, да