Как устроены словари в Python, часть 1.
Представьте себе огромную библиотеку, в которой вы хотите найти «Пикник на обочине». Как это сделать?
Наивный способ — перебирать. Взять первую книгу, понять, что это не Стругацкие, поставить обратно, взять следующую, ... и так далее. В лучшем случае «Пикник на обочине» окажется в первой ячейке и мы справимся за один ход. В худшем придется перебрать все n книг библиотеки, за за O(n) шагов. Но можно быстрее.
Для этого определим функцию, которая получает название книги и возвращает число. Такая функция-справочник:
«Пикник на обочине» -> 1
«Декамерон» -> 2
«Уловка 22» -> 3
...
Положим «Пикник на обочине» на первую полку, «Декамерон» на вторую, и так далее. Когда нам понадобится книга, мы отправим название в эту функцию и сразу получим номер ячейки. Теперь книгу можно найти всего за два шага:
1) вычислить номер книги по названию,
2) найти ее на полке с этим номером.
Получается сложность O(1) и это очень быстро! Положить книгу на свое место тоже можно за фиксированное число шагов, вне зависимости от размера библиотеки. Побочным эффектом такого подхода будет то, что в библиотеке не будет дубликатов книг, ведь все копии Декамерона будут попадать в ячейку с одним и тем же адресом.
Функция, которая ставит объекту в соответствие число, называется хеш-функцией. Любая хеш-функция должна удовлетворять требованию:
Если два объекта идентичны, то их хеши равны.
Идеальная хеш-функция должна удовлетворять еще одному требованию:
Если у двух объектов одинаковый хеш, то это одинаковые объекты.
На практике даже хорошую хеш-функцию написать сложно. Поэтому иногда бывает так, что хеш-функция возвращает два одинаковых числа для разных входных данных. Например, если хеш-функция вернула
«Облачный атлас» -> 10
«Москва-Петушки» -> 10
то это значит, что мы должны поставить две разные книги на одну полку. И когда мы приходим за книгой с номером 10, становится непонятно, какую из книг выбрать.
Представьте себе огромную библиотеку, в которой вы хотите найти «Пикник на обочине». Как это сделать?
Наивный способ — перебирать. Взять первую книгу, понять, что это не Стругацкие, поставить обратно, взять следующую, ... и так далее. В лучшем случае «Пикник на обочине» окажется в первой ячейке и мы справимся за один ход. В худшем придется перебрать все n книг библиотеки, за за O(n) шагов. Но можно быстрее.
Для этого определим функцию, которая получает название книги и возвращает число. Такая функция-справочник:
«Пикник на обочине» -> 1
«Декамерон» -> 2
«Уловка 22» -> 3
...
Положим «Пикник на обочине» на первую полку, «Декамерон» на вторую, и так далее. Когда нам понадобится книга, мы отправим название в эту функцию и сразу получим номер ячейки. Теперь книгу можно найти всего за два шага:
1) вычислить номер книги по названию,
2) найти ее на полке с этим номером.
Получается сложность O(1) и это очень быстро! Положить книгу на свое место тоже можно за фиксированное число шагов, вне зависимости от размера библиотеки. Побочным эффектом такого подхода будет то, что в библиотеке не будет дубликатов книг, ведь все копии Декамерона будут попадать в ячейку с одним и тем же адресом.
Функция, которая ставит объекту в соответствие число, называется хеш-функцией. Любая хеш-функция должна удовлетворять требованию:
Если два объекта идентичны, то их хеши равны.
Идеальная хеш-функция должна удовлетворять еще одному требованию:
Если у двух объектов одинаковый хеш, то это одинаковые объекты.
На практике даже хорошую хеш-функцию написать сложно. Поэтому иногда бывает так, что хеш-функция возвращает два одинаковых числа для разных входных данных. Например, если хеш-функция вернула
«Облачный атлас» -> 10
«Москва-Петушки» -> 10
то это значит, что мы должны поставить две разные книги на одну полку. И когда мы приходим за книгой с номером 10, становится непонятно, какую из книг выбрать.
🔥1
Как устроены словари в Python, часть 2.
Какое отношение эта проблема имеет к Python? Дело в том, что множества и словари в Python реализованы как хеш-таблицы, — то есть, ровно такие библиотеки с книгами на полках. Когда вы помещаете пару ключ-значение в словарь, интерпретатор вычисляет хеш ключа и кладет значение в ячейку памяти с адресом, совпадающим с результатом работы хеш-функции.
И если вдруг оказывается, что «Облачный атлас» и «Москва-Петушки» нужно положить в одну и ту же ячейку, то такую ситуацию называют коллизией.
Способов бороться с хеш-коллизиями концептуально два.
🐙 Метод цепочки. В этом методе каждая ячейка массива — это указатель на связный список пар ключ-значение, соответствующих одному и тому же хеш-значению ключа. Коллизии просто приводят к тому, что появляются цепочки длиной больше одного элемента.
Это как если положить все книги с одинаковым номером на одну полку. Тогда при поиске книги придется найти нужную полку, взять первую книгу и прочитать название. Если не та — проверить следующую, и так далее. В худшем случае все n книг попадут на одну полку и сложность получится O(n).
🐙 Открытая адресация. В этом случае в ячейки помещаются не указатели на списки, а сами пары ключ-значение. Алгоритм такой: вычисляем хеш-функцию, проверяем нужную ячейку. Если искомого элемента нет, то ищем в следующей ячейке. Следующую ячейку выбирают разными методами: это может быть просто фиксированный интервал до следующей ячейки, повторное хеширование вспомогательной хеш-функцией или другие методы.
Говоря языком библиотекаря, в этом случае библиотека получается большая, но полупустая. Потому что если полка, на которую вы хотели положить книгу, оказалась занята, вы выбираете другую свободную полку и кладете книгу туда. А потом по такому же алгоритму вычисляете, где находится нужная книга.
В Python множествах и словарях используется метод открытой адресации.
Какие из всего этого выводы?
🐙 Ключи словаря должны быть хешируемыми.
🐙 Словари неэффективны по памяти. Если экономите память, используйте кортежи.
🐙 Поиск по ключу в итоге не O(1), но все равно очень быстрый.
🐙 Модифицировать словарь, по которому итерируешься — плохая идея. Интерпретатор может решить, что пора ресайзить хеш-таблицу и тогда старые данные переедут в новую табличку. Не стоит.
И все то же самое применимо к множествам, потому что они реализованы похожим образом.
🐙 А ещё становится понятно, что множества работают сильно быстрее списоков.
Кстати, пост не содержит совсем никаких рекомендаций, что почитать на досуге. 🐠
#словари #множества #реализация #алгоритмы #хеширование
Какое отношение эта проблема имеет к Python? Дело в том, что множества и словари в Python реализованы как хеш-таблицы, — то есть, ровно такие библиотеки с книгами на полках. Когда вы помещаете пару ключ-значение в словарь, интерпретатор вычисляет хеш ключа и кладет значение в ячейку памяти с адресом, совпадающим с результатом работы хеш-функции.
И если вдруг оказывается, что «Облачный атлас» и «Москва-Петушки» нужно положить в одну и ту же ячейку, то такую ситуацию называют коллизией.
Способов бороться с хеш-коллизиями концептуально два.
🐙 Метод цепочки. В этом методе каждая ячейка массива — это указатель на связный список пар ключ-значение, соответствующих одному и тому же хеш-значению ключа. Коллизии просто приводят к тому, что появляются цепочки длиной больше одного элемента.
Это как если положить все книги с одинаковым номером на одну полку. Тогда при поиске книги придется найти нужную полку, взять первую книгу и прочитать название. Если не та — проверить следующую, и так далее. В худшем случае все n книг попадут на одну полку и сложность получится O(n).
🐙 Открытая адресация. В этом случае в ячейки помещаются не указатели на списки, а сами пары ключ-значение. Алгоритм такой: вычисляем хеш-функцию, проверяем нужную ячейку. Если искомого элемента нет, то ищем в следующей ячейке. Следующую ячейку выбирают разными методами: это может быть просто фиксированный интервал до следующей ячейки, повторное хеширование вспомогательной хеш-функцией или другие методы.
Говоря языком библиотекаря, в этом случае библиотека получается большая, но полупустая. Потому что если полка, на которую вы хотели положить книгу, оказалась занята, вы выбираете другую свободную полку и кладете книгу туда. А потом по такому же алгоритму вычисляете, где находится нужная книга.
В Python множествах и словарях используется метод открытой адресации.
Какие из всего этого выводы?
🐙 Ключи словаря должны быть хешируемыми.
🐙 Словари неэффективны по памяти. Если экономите память, используйте кортежи.
🐙 Поиск по ключу в итоге не O(1), но все равно очень быстрый.
🐙 Модифицировать словарь, по которому итерируешься — плохая идея. Интерпретатор может решить, что пора ресайзить хеш-таблицу и тогда старые данные переедут в новую табличку. Не стоит.
И все то же самое применимо к множествам, потому что они реализованы похожим образом.
🐙 А ещё становится понятно, что множества работают сильно быстрее списоков.
Кстати, пост не содержит совсем никаких рекомендаций, что почитать на досуге. 🐠
#словари #множества #реализация #алгоритмы #хеширование
👍2🔥1
Дублирование объектов в множестве
Пусть у нас есть сервер и его клиенты. На сервере мы хотим учитывать состояние клиентов и управлять ими. Для этого будем добавлять клиенты в множество, чтобы случайно не учесть один и тот же клиент на сервере дважды.
Создадим класс
Интерпретатор при добавлении объекта в множество следует правилу:
если
Для того, чтобы сравнивать объекты, множества и словари используют магический метод
🦑 в версиях Python 2.6 и ниже да, было просто
То есть, рассчитывать на то, что
Так как в нашем примере объекты разные и располагаются в разных ячейках памяти, то
Для этого исправим определение класса:
🦑 Перегрузить методы
🦑 Если объекты идентичны, то и их хеши должны быть равны
🦑 В хэш-функцию должно попадать то, что однозначно идентифицирует объект
🦑 Хеш объекта не должен меняться в течение его жизни (иначе будете ловить чудеса в run time) 🐠
#словари #множества #реализация #хеширование
Пусть у нас есть сервер и его клиенты. На сервере мы хотим учитывать состояние клиентов и управлять ими. Для этого будем добавлять клиенты в множество, чтобы случайно не учесть один и тот же клиент на сервере дважды.
Создадим класс
Client
и добавим его в множество (сразу определила метод repr
, чтобы были красивые принты): class Client:
def __init__(self, user_name):
self.user_name = user_name
def __repr__(self):
return self.user_name
fish1 = Client(user_name="catfish")
clients = set()
clients.add(fish1)
print(clients) # {catfish}
Круто, все работает из коробки! Попробуем теперь добавить второй клиент, чтобы увидеть, что дублирования нет:
fish2 = Client(user_name="catfish")
clients.add(fish2)
print(clients) # {catfish, catfish}
Как же так? Мы добавили в множество два совершенно одинаковых экземпляра и ждали, что останется только один, но сохранились оба. Интерпретатор при добавлении объекта в множество следует правилу:
если
a == b
, то обязательно hash(a) == hash(b)
То есть, сравнивает между собой как сами объекты, так и их хеши. Для того, чтобы сравнивать объекты, множества и словари используют магический метод
eq
. Для пользовательских объектов он определен по умолчанию. И по умолчанию два разных объекта не равны, даже если они абсолютно идентичны:
print(fish1 == fish2) # False
По умолчанию все объекты в Python также хешируемы. Когда мы пытаемся добавить объект в множество, мы используем магический метод этого объекта hash
, который тоже определен по умолчанию. Часто люди думают, что хеш объекта совпадает с его адресом в памяти, но это не всегда так: 🦑 в версиях Python 2.6 и ниже да, было просто
hash(x) = id()
🦑
с версии 2.6 и выше: hash(x)==id(x)/16
То есть, рассчитывать на то, что
hash(x) = id()
, нельзя. Но можно рассчитывать на то, что Python объектах по умолчанию есть hash
, который зависит от id()
и на то, что хеш объекта в течение его жизни не меняется. Так как в нашем примере объекты разные и располагаются в разных ячейках памяти, то
print(hash(fish1), hash(fish2)) # 8786876890805 8786876904409
Так что делать, чтобы объекты, которые мы хотим считать одинаковыми, схлопывались во множестве? Перегрузить методы hash
и eq
, чтобы в явном виде дать интерпретатору инструкцию, как сравнивать объекты и как рассчитывать хеш. Для этого исправим определение класса:
class Client:
def __init__(self, user_name):
self.user_name = user_name
def __repr__(self):
return self.user_name
def __hash__(self):
return hash(self.user_name)
def __eq__(self, other):
if self.user_name == other.user_name:
return True
else:
return False
Теперь при добавлении объектов в множество все работает как ожидали:
clients = set()
fish1 = Client(user_name="catfish")
clients.add(fish1)
fish2 = Client(user_name="catfish")
clients.add(fish2)
print(clients) # {catfish}
Помните, для того, чтобы объект класса, который вы определили сами, можно было добавить во множество или словарь, нужно: 🦑 Перегрузить методы
hash
и eq
, причем оба, иначе не заработает🦑 Если объекты идентичны, то и их хеши должны быть равны
🦑 В хэш-функцию должно попадать то, что однозначно идентифицирует объект
🦑 Хеш объекта не должен меняться в течение его жизни (иначе будете ловить чудеса в run time) 🐠
#словари #множества #реализация #хеширование
🔥1
Магические методы и пустые списки
Методы с двойным подчеркиванием в начале и в конце, например,
Например, метод
Зачем нам это? Это нестареющая классика: чтобы проверить, словарь или список на непустоту, начинающие часто используют стиль как в C++:
Для пользовательских объектов, где
Что с этим делать? Помнить, что falsy (значения, которые оцениваются как False) в Python это:
🐙 пустые словари
🐙 списки
🐙 кортежи
🐙 множества
🐙 строки
🐙 пустые
🐙 нули любого численного типа:
🐙 любые пользовательские объекты по умолчанию
🐙 непустые словари, множества, строки, списки, ...
🐙 константа
Методы с двойным подчеркиванием в начале и в конце, например,
__eq__
, __hash__
, __init__
, в Python называют магическими методами. Их назвали так, потому что они добавляют магию✨ в поведение класса. Например, метод
__init__
неявно вызывается при инициализации объекта: Foo:
def __init__(self, a, b):
self.a = a
self.b = b
foo = Foo(7, 9) # вызывается __init__
print(foo.a, foo.b) # 7, 9
Но сегодня я хочу поговорить о магичесом методе __bool__
. В тех классах, где этот метод определен, он сообщает интерпретатору, как оценить булево значение произвольного объекта. Зачем нам это? Это нестареющая классика: чтобы проверить, словарь или список на непустоту, начинающие часто используют стиль как в C++:
if len(a) != 0:
pass
В то время как PEP8 рекомендует делать просто:
if not a:
pass
И это работает ровно потому, что в момент if a:
вызывается метод __bool__
класса список. Для пользовательских объектов, где
__bool__
не перегружен, по умолчанию возвращается True
.
if foo:
print(True)
else:
print(False)
# True
Но если добавить Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def __bool__(self):
return False
То поведение изменится:
if foo:
print(True)
else:
print(False)
# False
Кстати, в случае, если метода __bool__
в классе нет, то интерпретатор будет искать метод __len__
(длина). Поведение такое же: если __len__
возвращает 0, то логическое значение оценивается как False
. Что с этим делать? Помнить, что falsy (значения, которые оцениваются как False) в Python это:
🐙 пустые словари
{}
,🐙 списки
[]
, 🐙 кортежи
()
, 🐙 множества
set()
, 🐙 строки
""
, 🐙 пустые
range(0)
, 🐙 нули любого численного типа:
0
, 0.0
, 0j
🐙 константы None
и собственно False
А truthy значения это: 🐙 любые пользовательские объекты по умолчанию
🐙 непустые словари, множества, строки, списки, ...
🐙 константа
True
И писать проверку на непустоту красиво: not a:
pass
#magic #dunder #bool #len #truthy #falsy #начинающим🔥1
Как правильно произносить название языка?
По-простому говорят «питон», так же название языка и переводится.
За это можно огребсти в сообществе, потому что по-православному, канонично говорить «пайтон». Ведь создатель языка Гвидо Ван Россум назвал язык в честь шоу «Летающий цирк Монти Пайтона», которое он очень любил.
Кстати, название для шоу рождалось в муках. Среди имен, из которых выбирали, были:
- Owl Stretching Time,
- The Toad Elevating Moment,
- A Horse, a Spoon and a Bucket,
- Vaseline Review,
- Bun, Wackett, Buzzard, Stubble and Boot.
(непереводимая игра слов, суть которой сводится к тому, что могло быть несколько иначе)
Название шоу не означает буквально ничего, а слово Python выбрали, потому что хотели добавить в название склизкости за счет змеи.
Семейство змей, в свою очередь, назвал питонидами французский зоолог Франсуа-Мари Доден в честь дракона, которого, согласно мифу, умертвил Аполлон у входа в Дельфийский оракул. Дракона звали Пифоном.
В общем, любителям копнуть поглубже история предлагает сразу несколько вариантов произношения. 🐍
#название #начинающим
По-простому говорят «питон», так же название языка и переводится.
За это можно огребсти в сообществе, потому что по-православному, канонично говорить «пайтон». Ведь создатель языка Гвидо Ван Россум назвал язык в честь шоу «Летающий цирк Монти Пайтона», которое он очень любил.
Кстати, название для шоу рождалось в муках. Среди имен, из которых выбирали, были:
- Owl Stretching Time,
- The Toad Elevating Moment,
- A Horse, a Spoon and a Bucket,
- Vaseline Review,
- Bun, Wackett, Buzzard, Stubble and Boot.
(непереводимая игра слов, суть которой сводится к тому, что могло быть несколько иначе)
Название шоу не означает буквально ничего, а слово Python выбрали, потому что хотели добавить в название склизкости за счет змеи.
Семейство змей, в свою очередь, назвал питонидами французский зоолог Франсуа-Мари Доден в честь дракона, которого, согласно мифу, умертвил Аполлон у входа в Дельфийский оракул. Дракона звали Пифоном.
В общем, любителям копнуть поглубже история предлагает сразу несколько вариантов произношения. 🐍
#название #начинающим
❤1
Дэвид Бизли, звезда Python сообщества и автор бомбических докладов про асинхронность в Python, выпустил бесплатный курс Practical Python Programming.
Курс не рассчитан на новичков, скорее на программистов, которые уже знакомы с основами Python или с другим языком. Курс не про веб-программирование, а про сам язык, так что инженерам и ученым тоже будет полезно.
Бизли сам пишет на Python 25 лет и половину этого времени преподает его, доверять можно. Очень рекомендую!
Курс не рассчитан на новичков, скорее на программистов, которые уже знакомы с основами Python или с другим языком. Курс не про веб-программирование, а про сам язык, так что инженерам и ученым тоже будет полезно.
Бизли сам пишет на Python 25 лет и половину этого времени преподает его, доверять можно. Очень рекомендую!
practical-python
Welcome!
Practical Python Programming (course by @dabeaz)
🔥1
Целочисленное деление
Как вы знаете, в Python есть два способа делить целые числа:
Оператор
Поэтому часть сообщества (включая Гвидо) настаивала на том, что оператором целочисленного деления нужно выбрать символ
Вот что Гвидо пишет об этом в своем блоге (в моем вольном переводе):
Чтобы услышать мнение человека, далекого от программирования, я спросил свою подругу, которая занималась средневековой английской литературой. Разговор был примерно такой:
Я: Вот ты берешь два целых числа. Хорошо?
Она: Хорошо!
Я: Теперь ты можешь их сложить, вычесть, умножить в программе, правильно?
Она: Хм, конечно!
Я: А теперь предположим, что ты их делишь...
Она: Но в этом нет смысла! Целые числа образуют кольцо, а не поле. Ты ведь сказал, что взял эти числа из Z, верно?
Я: Ага.
Вот и все. Это точка зрения непрограммиста (с которой мне удобно согласиться). Целочисленное деление — это чушь и его не нужно писать как "/", даже если в C делают именно так;-)
Действительно, с точки зрения непрограммиста, целочисленное деление довольно странная история, ведь над целыми числами, как и над матрицами, нет деления в принципе!
Источники: [1], [2].
Кстати, я сейчас готовлю курс по пайтон для начинающих (не то чтобы я считала, что на рынке мало курсов, но я просто люблю учить людей). Как считаете, стоит добавить этот фрагмент в курс, или лучше вырезать?
Как вы знаете, в Python есть два способа делить целые числа:
Оператор
/
при делении целого числа на целое возвращает результат типа float.
>>> 3 / 2
1.5 # float
А оператор //
при делении целого на целое возвращает целое с округлением вниз, по-английски этот оператор еще называют floor division.
>>> 3 // 2
1 # int
Копалась в истории языка и узнала, что изначально деление целых чисел в Python было только целочисленное, и для него Гвидо использовал символ /
. Но быстро стало понятно, что в языке, где программист не объявляет типы явно, использование такого символа неудобно и будет приводить к обилию ошибок в программах. Поэтому часть сообщества (включая Гвидо) настаивала на том, что оператором целочисленного деления нужно выбрать символ
//
, а оператор деления, который возвращает тип float, должен быть /
. Другие разработчики говорили, что целочисленное деление нужно писать как /
, аргументируя это тем, что «научиться обращаться с целочисленным делением — это как обряд инициации для начинающих программистов», да и в C целочисленное деление пишется именно так. Вот что Гвидо пишет об этом в своем блоге (в моем вольном переводе):
Чтобы услышать мнение человека, далекого от программирования, я спросил свою подругу, которая занималась средневековой английской литературой. Разговор был примерно такой:
Я: Вот ты берешь два целых числа. Хорошо?
Она: Хорошо!
Я: Теперь ты можешь их сложить, вычесть, умножить в программе, правильно?
Она: Хм, конечно!
Я: А теперь предположим, что ты их делишь...
Она: Но в этом нет смысла! Целые числа образуют кольцо, а не поле. Ты ведь сказал, что взял эти числа из Z, верно?
Я: Ага.
Вот и все. Это точка зрения непрограммиста (с которой мне удобно согласиться). Целочисленное деление — это чушь и его не нужно писать как "/", даже если в C делают именно так;-)
Действительно, с точки зрения непрограммиста, целочисленное деление довольно странная история, ведь над целыми числами, как и над матрицами, нет деления в принципе!
Источники: [1], [2].
Кстати, я сейчас готовлю курс по пайтон для начинающих (не то чтобы я считала, что на рынке мало курсов, но я просто люблю учить людей). Как считаете, стоит добавить этот фрагмент в курс, или лучше вырезать?
Blogspot
The Problem with Integer Division
Python's handling of integer division is an example of early mistake with huge consequences. As mentioned earlier, when Python was created...
👍1
Работа с JSON
Хотела собрать для менти ссылок по работе с JSON, но не нашла, чтобы в одном месте последовательно, исчерпывающе и без воды рассказали бы все самое важное, что питонисту нужно знать о работе с этим форматом.
Поэтому сделала лонгрид по JSON'у сама и делюсь с вами! Статью в PDF можно посмотреть на моем Patreon'e, она бесплатная. Рассчитана на уровень джуниоров и стажеров. В канал выложить не могу, потому что слишком много текста, а в тексте картинки, схемы и даже один мем!
Из головных болей: не получилось сверстать так идеально, как хотелось. Начала с LaTeX, поняла, что верстается долго, перешла в markdown, но там некрасиво легли картинки. Наконец, сделала в Notion и все равно недовольна. Дайте знать, если умеете красиво верстать без боли и адских страданий или можете рассказать, на какой платформе вам удобнее читать лонгриды.
🐠
Один из отзывов: Прочитал твою статью про json! Восторг! Ты так хорошо и спокойно объясняешь! Ты смогла мои обрывочные знания систематизировать.
Спасибо вам за такие хорошие слова🤍 Стараюсь для вас.
Хотела собрать для менти ссылок по работе с JSON, но не нашла, чтобы в одном месте последовательно, исчерпывающе и без воды рассказали бы все самое важное, что питонисту нужно знать о работе с этим форматом.
Поэтому сделала лонгрид по JSON'у сама и делюсь с вами! Статью в PDF можно посмотреть на моем Patreon'e, она бесплатная. Рассчитана на уровень джуниоров и стажеров. В канал выложить не могу, потому что слишком много текста, а в тексте картинки, схемы и даже один мем!
Из головных болей: не получилось сверстать так идеально, как хотелось. Начала с LaTeX, поняла, что верстается долго, перешла в markdown, но там некрасиво легли картинки. Наконец, сделала в Notion и все равно недовольна. Дайте знать, если умеете красиво верстать без боли и адских страданий или можете рассказать, на какой платформе вам удобнее читать лонгриды.
🐠
Один из отзывов: Прочитал твою статью про json! Восторг! Ты так хорошо и спокойно объясняешь! Ты смогла мои обрывочные знания систематизировать.
Спасибо вам за такие хорошие слова🤍 Стараюсь для вас.
🔥1
Открываю курс по Python.
Этой осенью ко мне в очередной раз зашла пара онлайн школ с предложением написать для них курс по Python. В очередной раз отказавшись, я решила сделать такой курс сама. После двух месяцев интенсивной и кропотливой работы я открываю продажи этого курса. 🐠
Курс подойдет вам если вы:
🐟 только начинаете программировать,
🐟 уже пытались изучать основы, но в знаниях хочется навести порядок.
О курсе:
🐟 Теория и задачи ждут вас на платформе Stepik.
🐟 Сейчас курс продается за 2700 рублей и можно пройти первые 5 модулей. Остальные 7 модулей я открою для прохождения в течение 7 недель.
🐟 Я внимательно слежу за комментариями и буду обновлять и дополнять материал там, где это будет нужно.
🐟 Когда я открою последний модуль, цена вырастет в полтора раза. Так что предлагаю заинтересованным опередить меня!
Научиться писать на Python под моим наблюдением можно здесь.
Этой осенью ко мне в очередной раз зашла пара онлайн школ с предложением написать для них курс по Python. В очередной раз отказавшись, я решила сделать такой курс сама. После двух месяцев интенсивной и кропотливой работы я открываю продажи этого курса. 🐠
Курс подойдет вам если вы:
🐟 только начинаете программировать,
🐟 уже пытались изучать основы, но в знаниях хочется навести порядок.
О курсе:
🐟 Теория и задачи ждут вас на платформе Stepik.
🐟 Сейчас курс продается за 2700 рублей и можно пройти первые 5 модулей. Остальные 7 модулей я открою для прохождения в течение 7 недель.
🐟 Я внимательно слежу за комментариями и буду обновлять и дополнять материал там, где это будет нужно.
🐟 Когда я открою последний модуль, цена вырастет в полтора раза. Так что предлагаю заинтересованным опередить меня!
Научиться писать на Python под моим наблюдением можно здесь.
Stepik: online education
Python для тех, у кого лапки
Хотите освоить Python без опыта программирования, но не знаете с чего начать? Этот курс специально для вас!
👍1
Блок else в циклах
Многие теряются при виде блока
С циклами
#циклы #for #while #else
Многие теряются при виде блока
else
в циклах. А между тем в Python он используется не только в условных конструкциях. Рассмотрим на примере цикла for
: Блок
for i in range(1, 3):
print(i)
else:
print("loop finished normally")
# 1
# 2
# loop finished normally
else
выполняется, если выполняется условие выхода из цикла. Это значит, что если цикл прерывается как-то иначе, например, ключевым словом break
или исключением, то блок else
выполнен не будет:Чаще всего этим пользуются, когда ищут что-нибудь в цикле с использованием ключевого слова
for i in range(1, 4):
if i == 2:
raise Exception("error occurred")
else:
print("loop finished normally")
# Exception: error occurred
break
:
numbers = [1, 3, 11, 5]
for number in numbers:
if number % 2 == 0:
print ("even number found")
break
else:
print ("no even numbers in the list")
# no even numbers in the list
С циклами
while
можете попробовать самостоятельно. 🐠#циклы #for #while #else
🔥1
Печать списков
Если вдруг на собеседовании вам понадобится вывести список (или множество) чисел на печать одной строкой, то вот изящный способ это сделать:
Пользуйтесь! 🐠
#списки #множества #iterables #print
Если вдруг на собеседовании вам понадобится вывести список (или множество) чисел на печать одной строкой, то вот изящный способ это сделать:
>>> numbers = [1, 2, 3, 4, 5]
>>> print(*numbers)
1 2 3 4 5
Пользуйтесь! 🐠
#списки #множества #iterables #print
🔥1
Прямой эфир о резюме
Пару дней назад в одном из чатов мелькнуло хорошее джуниорское резюме с комментарием, что на работу с таким резюме почему-то не берут. Я уже писала текст о том, как лучше писать резюме, но после разговора в чате поняла, что не получается составить исчерпывающий гайд, как себя представить: хоть и есть хорошие практики, но все косяки слишком индивидуальны. И каждое резюме надо разбирать отдельно.
Поэтому предлагаю вам вот такой формат: мы с моей коллегой, senior разработчицей и основательницей школы IT girl school Алисой проведем в четверг в 20:00 прямой эфир, на котором разберем и перепишем три джуниорских резюме. Увидите на примерах, как лучше писать, чтобы вас заметили работодатели.
Перерабатывать резюме будем прямо в эфире и еще будем задавать уточняющие вопросы, чтобы представить опыт кандидата в самом выгодном свете. Поэтому ищем троих добровольцев, готовых участвовать в эфире. В конце участники получат переработанные нами версии своих CV, а зрители — набор рекомендаций и инсайты на тему того, как видят их резюме работодатели.
На эфир приглашаем стажеров, джуниор программистов и тех, кто интересуется темой. Старт в 20:00 в четверг 24 декабря, участие бесплатное. Добавьте событие в свои календари, чтобы не забыть.
Ссылка на эфир: https://us02web.zoom.us/j/86743972942?pwd=eHVIeUFvSklGaUZaK3N2WnlUSDFxZz09
Резюме для разбора можно прислать мне или Алисе.
Ставьте огонек, если собираетесь прийти, чтобы я понимала, сколько нас будет🔥
Пару дней назад в одном из чатов мелькнуло хорошее джуниорское резюме с комментарием, что на работу с таким резюме почему-то не берут. Я уже писала текст о том, как лучше писать резюме, но после разговора в чате поняла, что не получается составить исчерпывающий гайд, как себя представить: хоть и есть хорошие практики, но все косяки слишком индивидуальны. И каждое резюме надо разбирать отдельно.
Поэтому предлагаю вам вот такой формат: мы с моей коллегой, senior разработчицей и основательницей школы IT girl school Алисой проведем в четверг в 20:00 прямой эфир, на котором разберем и перепишем три джуниорских резюме. Увидите на примерах, как лучше писать, чтобы вас заметили работодатели.
Перерабатывать резюме будем прямо в эфире и еще будем задавать уточняющие вопросы, чтобы представить опыт кандидата в самом выгодном свете. Поэтому ищем троих добровольцев, готовых участвовать в эфире. В конце участники получат переработанные нами версии своих CV, а зрители — набор рекомендаций и инсайты на тему того, как видят их резюме работодатели.
На эфир приглашаем стажеров, джуниор программистов и тех, кто интересуется темой. Старт в 20:00 в четверг 24 декабря, участие бесплатное. Добавьте событие в свои календари, чтобы не забыть.
Ссылка на эфир: https://us02web.zoom.us/j/86743972942?pwd=eHVIeUFvSklGaUZaK3N2WnlUSDFxZz09
Резюме для разбора можно прислать мне или Алисе.
Ставьте огонек, если собираетесь прийти, чтобы я понимала, сколько нас будет🔥
Telegram
Python in depth
Как писать резюме
Если вы хотите продать на рынке труда свое время и навыки, то резюме -- это не только рассказ о том, как вы дошли до такой жизни, но и ваш продающий текст. Я пишу резюме, чтобы показать читателю, что могу быть ему полезна и убедить пригласить…
Если вы хотите продать на рынке труда свое время и навыки, то резюме -- это не только рассказ о том, как вы дошли до такой жизни, но и ваш продающий текст. Я пишу резюме, чтобы показать читателю, что могу быть ему полезна и убедить пригласить…
👍1
Вот запись вчерашнего эфира с разбором резюме. Сначала там рассказ минут на 10 от меня про самые частые ошибки в резюме, а дальше мы с Алисой разбираем и комментируем 4 совершенно разных документа и отвечаем на вопросы из чата.
Запись вот: https://youtu.be/AZe4_XVRuxA
Если то, что мы делаем на эфире, кажется вам полезным и близким, но все равно непонятно, как именно вам получить повышение или работу, то приходите в личку @chakchurina, обсудим, что можно сделать в вашем случае.
Запись вот: https://youtu.be/AZe4_XVRuxA
Если то, что мы делаем на эфире, кажется вам полезным и близким, но все равно непонятно, как именно вам получить повышение или работу, то приходите в личку @chakchurina, обсудим, что можно сделать в вашем случае.
Telegram
Алиса про IT
Программистка и карьерный навигатор. Помогаю хакнуть поиск работы, вырасти в зарплате и построить жизнь мечты. Честно, с душой и без воды❤️
PR @AgatyaR
Блогер #4856856718
PR @AgatyaR
Блогер #4856856718
Прикольные новости Jupyter: теперь его можно запустить прямо в excel'е. Кому-то покажется, что это дорога в ад, а кого-то избавит от необходимости выбирать между привычными инструментами для аналитики. Что думаете?
Источник: https://www.pyxll.com/blog/python-jupyter-notebooks-in-excel/
Источник: https://www.pyxll.com/blog/python-jupyter-notebooks-in-excel/
Замена в списке
Расскажу, как заменить часть значений в списке, пользуясь синтаксическим сахаром языка. Пусть есть два списка:
#списки #коллекции #слайсы
Расскажу, как заменить часть значений в списке, пользуясь синтаксическим сахаром языка. Пусть есть два списка:
>>> a = [1, 2, 3, 4, 10]
>>> b = [5, 6, 7]
нужно получить:
[1, 5, 6, 7, 10]
Делаем:
>>> a[1:4] = b
Получаем:
>>> a
[1, 5, 6, 7, 10]
Готово, вы восхитительны! #списки #коллекции #слайсы
🔥1
Релиз NumPy
Вчера вышел самый крупный в истории NumPy релиз: версия 1.20.0. Библиотека в этой версии поддерживает Python 3.7 — 3.9, а ниже нет. Если работаете с NumPy, посмотрите полный список изменений. 🐠
#новости
Вчера вышел самый крупный в истории NumPy релиз: версия 1.20.0. Библиотека в этой версии поддерживает Python 3.7 — 3.9, а ниже нет. Если работаете с NumPy, посмотрите полный список изменений. 🐠
#новости
👍1
Друзья, я закончила свой курс по Python для начинающих.
🐙 Несколько мест переработала по отзывам.
🐙 Когда я пишу, промахиваюсь по клавишам и в курсе было много опечаток, которые мы со студентами исправили.
🐙 Сделала чат поддержки, в котором помогаю и отвечаю на вопросы (после регистрации приходит ссылка на почту).
🐙 Курс одобрен командой Степик и попал в рекомендации платформы.
🐙 Как и обещала, когда закончила делать материалы, подняла цену на курс.
🐙 Добавила сертификат о прохождении.
🐙 Вернула историческое название, так что в сертификате будет именно оно.
Вскрылись и проблемы: я стараюсь быть максимально открытой, отвечаю на все вопросы в комментариях, сделала чат в телеграме, но студенты все равно мало задают вопросов. А я бы хотела, чтобы спрашивали, общались друг с другом и чтобы быстрее справлялись со сложными местами.
Поэтому сейчас делаю группу, в которой буду вести студентов одним потоком. Хочу, чтобы был общий вайб, чтобы делились опытом, да и мне будет удобнее обсуждать и комментировать решения сразу для всех. В общем, организую условия, в которых смогу активнее участвовать в обучении.
Еще готовлюсь к тому, чтобы писать видео для курса: начну с визитки и дальше буду покрывать скринкастами места, которые даются сложно, их уже в целом видно по тому, как люди проходят курс.
Группа стартует 15 февраля и я рассчитываю на 6 недель: по 2 раздела в неделю. Получится плотно, но я буду помогать с задачами в чате, созваниваться по Зуму, делать review решений в группе. Набираю всего 30 человек, потому что больше мне самой будет сложно.
Если давно хотели выучить Python, но не знали, с чего начать, то давайте начнем вместе. 🐠
PS: после регистрации на почту придет ссылка на группу, не пропустите ее.
🐙 Несколько мест переработала по отзывам.
🐙 Когда я пишу, промахиваюсь по клавишам и в курсе было много опечаток, которые мы со студентами исправили.
🐙 Сделала чат поддержки, в котором помогаю и отвечаю на вопросы (после регистрации приходит ссылка на почту).
🐙 Курс одобрен командой Степик и попал в рекомендации платформы.
🐙 Как и обещала, когда закончила делать материалы, подняла цену на курс.
🐙 Добавила сертификат о прохождении.
🐙 Вернула историческое название, так что в сертификате будет именно оно.
Вскрылись и проблемы: я стараюсь быть максимально открытой, отвечаю на все вопросы в комментариях, сделала чат в телеграме, но студенты все равно мало задают вопросов. А я бы хотела, чтобы спрашивали, общались друг с другом и чтобы быстрее справлялись со сложными местами.
Поэтому сейчас делаю группу, в которой буду вести студентов одним потоком. Хочу, чтобы был общий вайб, чтобы делились опытом, да и мне будет удобнее обсуждать и комментировать решения сразу для всех. В общем, организую условия, в которых смогу активнее участвовать в обучении.
Еще готовлюсь к тому, чтобы писать видео для курса: начну с визитки и дальше буду покрывать скринкастами места, которые даются сложно, их уже в целом видно по тому, как люди проходят курс.
Группа стартует 15 февраля и я рассчитываю на 6 недель: по 2 раздела в неделю. Получится плотно, но я буду помогать с задачами в чате, созваниваться по Зуму, делать review решений в группе. Набираю всего 30 человек, потому что больше мне самой будет сложно.
Если давно хотели выучить Python, но не знали, с чего начать, то давайте начнем вместе. 🐠
PS: после регистрации на почту придет ссылка на группу, не пропустите ее.
Stepik: online education
Python для тех, у кого лапки
Хотите освоить Python без опыта программирования, но не знаете с чего начать? Этот курс специально для вас!
👍2
Круглый стол по Kubernetes
Допустим, в вашей компании решили перейти на Kubernetes. Это должно было повысить стабильность сервисов, увеличить скорость разработки... Но в реальности этого не произошло. В чем причина: Kubernetes не работает или процессы не отлажены?
Приходите на бесплатный круглый стол 11 февраля в 19:00. Поговорим о том, кто какие задачи решает в кластере Kubernetes, как уменьшить количество необходимых ресурсов для перехода на k8s, за счет чего сокращается time-to-market и причем тут вообще разработчик.
На встрече будут инженеры эксплуатации и разработчики из Mail.ru Cloud Solutions, Слёрм и Southbridge.
#ad
Допустим, в вашей компании решили перейти на Kubernetes. Это должно было повысить стабильность сервисов, увеличить скорость разработки... Но в реальности этого не произошло. В чем причина: Kubernetes не работает или процессы не отлажены?
Приходите на бесплатный круглый стол 11 февраля в 19:00. Поговорим о том, кто какие задачи решает в кластере Kubernetes, как уменьшить количество необходимых ресурсов для перехода на k8s, за счет чего сокращается time-to-market и причем тут вообще разработчик.
На встрече будут инженеры эксплуатации и разработчики из Mail.ru Cloud Solutions, Слёрм и Southbridge.
#ad
👍1
Музыкальная пауза
Песни, которые слышим чаще, чем хочется
Песни, которые слышим чаще, чем хочется
1. func (1)
2. dct ['key'] = lst [index]
3. ham[ 1 ]
4. counter +=1
5. complex(real, imag = 0.0)
6. import sys, os
7. except Exception:
8. if type(obj) is
int
:
9. if len(values)
== 0
:
10. if flag == True
https://youtu.be/hgI0p1zf31kYouTube
🎵 The PEP 8 Song 🎵
A songification of that most holiest of Python Enhancement Proposals, the PEP 8.
Based on an idea by Daniel "Mr. Hemlock" Brown.
Written and performed by Leon Sandøy, A.K.A. lemonsaurus.
Music and melody from Mad World by Roland Orzabal. This version was…
Based on an idea by Daniel "Mr. Hemlock" Brown.
Written and performed by Leon Sandøy, A.K.A. lemonsaurus.
Music and melody from Mad World by Roland Orzabal. This version was…
👍1
Задача про скобки.
Супер распространенная задача со скрининг-собеседований.
На вход подается строка, состоящая из круглых скобок. Выведите
Например, если входная строка
А если
Это базовая задача на алгоритмы и решается она за один проход по строке (O(n)). Идея здесь следующая: нужно завести переменную-стек, которая будет хранить состояние скобки на i-том шаге и в зависимости от состояния принимать решение о том, валидная строка или нет.
Вот видео с более подробным описанием решения.
Я видела варианты, в которых люди пишут свой класс для стека, но в качестве него сработает и обычный список, если использовать только методы
Вот возможное решение, которое мне нравится:
Можете решить ее самостоятельно. 🐠
UPD: в комментарии накинули решение без стека:)
Супер распространенная задача со скрининг-собеседований.
На вход подается строка, состоящая из круглых скобок. Выведите
True
, если скобки вложены правильно и False
, если нет.Например, если входная строка
(()(()))
, то ответ должен быть True
. А если
())
, то False
. Это базовая задача на алгоритмы и решается она за один проход по строке (O(n)). Идея здесь следующая: нужно завести переменную-стек, которая будет хранить состояние скобки на i-том шаге и в зависимости от состояния принимать решение о том, валидная строка или нет.
Вот видео с более подробным описанием решения.
Я видела варианты, в которых люди пишут свой класс для стека, но в качестве него сработает и обычный список, если использовать только методы
append()
и pop()
. Вот возможное решение, которое мне нравится:
def if_balanced(string):
stack = []
for i in string:
if i == "(":
stack.append(i)
elif i == ")":
if not stack:
return False
stack.pop()
if stack:
return False
return True
print(if_balanced("()()())"))
Усложненная форма этой же задачи: на вход подаются строка со скобками разных видов, например, ([]{}) -> True
, ({}([]{)}) -> False
. Можете решить ее самостоятельно. 🐠
UPD: в комментарии накинули решение без стека:)
YouTube
Check for balanced parentheses in an expression | GeeksforGeeks
Find Complete Code at GeeksforGeeks Article: http://www.geeksforgeeks.org/check-for-balanced-parentheses-in-an-expression/
Practice Problem: http://practice.geeksforgeeks.org/problems/parenthesis-checker/0
Read More: https://www.geeksforgeeks.org/check…
Practice Problem: http://practice.geeksforgeeks.org/problems/parenthesis-checker/0
Read More: https://www.geeksforgeeks.org/check…
🔥1
Задача о циклическом сдвиге
Предложила ее менти как тренировочную.
Циклический сдвиг массива — это когда каждый элемент кроме последнего сдвигается вправо, а последний элемент массива становится первым.
На вход подаются массив
Например, для данных:
Циклический сдвиг должен быть выполнен трижды:
И программа должна вернуть
Если
Для
Наивное решение:
1. Определяем, что такое ротировать массив один раз.
2. Делаем это K раз.
Это решение не оптимальное, потому что каждый
Как решила ученица. Она заметила, что индексы элементов в новом массиве несложно рассчитать аналитически:
Это круче, потому что
🐙 результат получается за один проход
🐙 и время работы не увеличивается на больших
Очень радуюсь, когда получается у учеников!
Предложила ее менти как тренировочную.
Циклический сдвиг массива — это когда каждый элемент кроме последнего сдвигается вправо, а последний элемент массива становится первым.
На вход подаются массив
A
и целое число K
. Сделайте циклический сдвиг входного массива K
раз и верните получившийся массив. Например, для данных:
A = [2, 5, 1, 4, 6]
K = 3
Циклический сдвиг должен быть выполнен трижды:
[2, 5, 1, 4, 6] -> [6, 2, 5, 1, 4]
[6, 2, 5, 1, 4] -> [4, 6, 2, 5, 1]
[4, 6, 2, 5, 1] -> [1, 4, 6, 2, 5]
И программа должна вернуть
[1, 4, 6, 2, 5]
Если
K = 0
, то сдвиг не делается.Для
K = 5
:
[2, 5, 1, 4, 6] -> [2, 5, 1, 4, 6]
Наивное решение:
1. Определяем, что такое ротировать массив один раз.
2. Делаем это K раз.
def rotate(A, K):
""" Rotates a list K times """
if not A:
return []
for i in range(K):
A = rotate_once(A)
return A
def rotate_once(A):
""" Rotates a list once """
A.insert(0, A[-1])
del A[-1]
return A
Это решение не оптимальное, потому что каждый
insert()
передвигает все элементы исходного списка. Также оно не учитывает, что после len(A)
ротаций список возвращается в исходное состояние. Как решила ученица. Она заметила, что индексы элементов в новом массиве несложно рассчитать аналитически:
def rotate(A, K):
""" Rotates a list K times """
result = []
if K == 0:
return A
else:
for i in range(len(A)):
new_index = (i - K) % len(A)
result.append(A[new_index])
return result
Это круче, потому что
🐙 результат получается за один проход
🐙 и время работы не увеличивается на больших
K
.Очень радуюсь, когда получается у учеников!
👍2