CoolPython
4.64K subscribers
20 photos
44 links
Канал об основах Python и хороших практиках разработки. Создаём системность в обрывочных знаниях.

Тем, кто хочет понимать, что пишет!
Download Telegram
Грусти пост о формулах в коде

Подсмотрела, как коллеги, которые пишут на C++, оформляют формулы. Здесь закомментировали черту и разбили ей формулу геометрической прогрессии на числитель и знаменатель. Получилась очень читаемо, а еще функция документирует себя сама!
 
//Sum of first n terms of a geometric series.
// S = a + ar + ar^2 + ... + ar^n

float geom_sum(int n, float a, float r)
{
return
(a*(1 - pow(r, n + 1)))
/ //-----------------------
(1 - r);
}


Мне этот стиль очень нравится, но жаль, что интерпретатор так не позволяет писать в исполняемом коде. По крайней мере, у меня не получилось сделать, чтобы похожее форматирование заработало. Поэтому в теле функции я обычно пишу числитель и знаменатель отдельно, чтобы не было очень длинно, а выражение в docstring'е оформляю именно так. На Python получается что-то вроде:
 
def geom_sum(n, a, r):
"""
Sum of first n terms of a geometric series.
S = a + ar + ar^2 + ... + ar^n

1 - pow(r, n + 1)
S = a -----------------
1 - r

:param n: Number of terms
:param a: First term
:param r: Common ratio, r < 1
:return: Sum of series
"""

num = a*(1 - pow(r, n + 1))
denom = 1 - r
return num/denom


Не стала обрабатывать случай расхождения ряда, я сейчас не об этом. А так хорошо бы. Такие дела! 🐠

#кодстайл #докстринг #формулы #комментарии #вообще_другой_язык #cpp
👍1
​​Введение в декораторы

В нескольких следующих постах я хочу поговорить о декораторах. Будет базовое определение, мотивация их использовать, всякие хитрости, а еще куча примеров.

Прежде, чем говорить о декораторах, нужно кое- что узнать о функциях в Python. Допустим, у нас есть функция, которая здоровается с Юпи:

def hey_Jupi():
print("Привет, Юпи!")

Функции в Python -- это объекты первого класса, ничем не хуже, чем int'ы или словари. Это значит, что:

🐙 Функцию можно присвоить переменной:

say_hi = hey_Jupi
say_hi()
# Привет, Юпи!

🐙 Функцию можно вернуть из функции:

def wrapper(func):
print("Юпи пришла.")
return func

hello_Jupi = wrapper(hey_Jupi)
# Юпи пришла.
hello_Jupi()
# Привет, Юпи!

🐙 Функцию можно определить внутри другой функции:

def deco(func):
def wrapper():
print("Юпи пришла.")
func()
return wrapper

hey_Jupi = deco(hey_Jupi)
hey_Jupi()
# Юпи пришла.
# Привет, Юпи!

Смотрите, что получилось на последнем шаге. На этапе создания deco никакой код не выполняется -- мы заходим в deco, видим, что здесь определена функция wrapper и возвращаем ее. Таким образом мы подменяем исходную hey_Jupi на wrapper и получаем новое поведение hey_Jupi, не изменяя ее код!

Это и называется декоратор. Это настолько удобный и мощный инструмент, что в Python для него придумали специальный синтаксический сахар. При условии, что функция deco у нас уже определена так же, как выше, можно добавить название декоратора с символом @ перед определением функции и получить эквивалентное поведение:

@deco
def hey_Jupi():
print("Привет, Юпи!")

hey_Jupi()
# Юпи пришла.
# Привет, Юпи!

Кстати, этот же декоратор можно применить и к любой другой функции:

@deco
def take_five():
print("Юпи, дай пять!")

take_five()
# Юпи пришла.
# Юпи, дай пять!

Декораторы круты тем, что позволяют гибко модифицировать поведение функции, применять одну и ту же модификацию к нескольким функциям сразу и даже менять поведение функций, доступа к коду которых у нас нет! Зачем нам декораторы на реальных проектах?

🐙 Декораторы используют в веб фреймворках для проверки авторизации или для разделения групп пользователей. Например, часть методов доступна только авторизованным пользователям, либо пользователям с определенной ролью, а остальные методы -- всем. Для этого нужные методы оборачивают в декораторы, которые делают необходимые проверки.
🐙 Декораторы позволяют проверить, что аргументы функции имеют нужный тип и значения. Это можно сделать на входе в функцию, но иногда проверки переносят в функцию-обертку.
🐙 С помощью декоратора можно замерять время выполнения функций.

В следующих постах разберемся, как комбинировать декораторы и передавать в декоратор параметры. Всем пять!🐠

#декораторы #функциональный_стиль #функции #основы
🔥1
Комбинируем декораторы

Допустим, у нас есть функции, которые работают со строками. Возьмем, например, функцию, которая возвращает строчку из Zen of Python:

def readability():
return 'Readability counts'

print(readability())
Readability counts

А теперь мы хотим, чтобы можно было показать текст в двух вариантах: жирным и курсивом. Вот два декоратора, один из которых добавляет тег <<жирный>>, а второй <<курсив>> :

def bold(func):
def wrapper():
return '<b>' + func() + '</b>'
return wrapper

def italic(func):
def wrapper():
return '<i>' + func() + '</i>'
return wrapper

Как уже договаривались в прошлом посте, запись

@bold
def readable():
return 'Readability counts'

Эквивалентна записи

readable = bold(readable)

И после применения декоратора вызов функции дает текст

print(readable())
<b>Readability counts</b>

А что если мы хотим получить текст одновременно и жирный и с курсивом? Можно сделать композицию декораторов:

@italic
@bold
def readable():
return 'Readability counts'

print(readable())
<i><b>Readability counts</b></i>

Обратите внимание, что результат в зависимости от порядка применения декораторов будет разным:

@bold
@italic
def readable():
return 'Readability counts'

print(readable())
<b><i>Readability counts</i></b>

Так получается из-за разного порядка выполнения функций: в первом случае мы сначала добавляем тэг <<жирный>>, а сверху оборачиваем в <<курсив>>:

readable = italic(bold(readable))

А во втором -- наоборот:

readable = bold(italic(readable))

Читаемость имеет значение! И порядок тоже. 🐠

#декораторы #композиция #функциональный_стиль
👍1🔥1
Знакомая, которая недавно устроилась на работу джуниором, рассказала, что в ее команде новым сотрудникам ставят цель либо закоммитить кусочек кода за день, либо задать два вопроса.

По-моему, это прекрасная практика. Многим сложно спрашивать: не хочешь отвлекать коллег от задач, боишься показать, что чего-то не знаешь, ... Особенно в начале карьеры. Особенно на новом месте. Ну, и застреваешь постоянно, как следствие.

А так хоть проговорите с человеком, что задавать вопросы здесь законно. Можно еще поручить ответы на эти вопросы сразу добавить в доку, для будущих поколений 🐠

#онбординг #soft_skillz #личное
👍1
Давайте познакомимся

Я Маша Чакчурина, back-end разработчица🐠 Закончила физико-технический факультет в Питерском Политехе, занималась физикой Солнца, работала в компании СтарЛайн, и в их беспилотном автомобиле тоже. А год назад я переехала в Москву и проработала этот год в Касперском.

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

Я не верю, что можно научиться чему-то серьезному за пару дней. Для меня всегда работало узнавать вещи по чуть-чуть. Лучше дать себе время разобраться, чем потом жалеть, что пропустила и не успела. Поэтому я выбрала формат канала, где я могу делиться информацией маленькими порциями, чтобы я была уверена, что она укладывается.

Я пишу заметки по мере того, как они приходят в голову, но стараюсь выдерживать структуру так, чтобы, можно было постепенно двигаться от базовых к продвинутым темам. Поэтому если какой-нибудь текст кажется сложным, скорее всего, я уже кидала подводку к нему до этого. Подсказка: темы в канале удобно искать не только поиском, но и по хэштегам.

Надеюсь, что этот канал вам помогает узнать что-то новое или повторить уже известное.

Что можно сделать для меня:

🐬 Если у вас есть друзья, которые учат или хотят учить Python, поделитесь с ними ссылкой.
🐬 Напишите мне, если хочется читать о чем-нибудь определенном, и я об этом расскажу.
🐬 Если думаете, что я могу быть вам полезна, предложите мне сотрудничество.
🐬 О личном я пишу в инстаграме, добро пожаловать в мой профиль.

Ну и всем успехов! А еще интересных, своих, драйвовых задач 🐠

#личное
1
​​IT во время COVID-19

Эпидемия для всех разная: кому-то не хватает общения в карантине, у кого-то болеет знакомый, кто-то успел лишиться работы, у некоторых трещит по швам бизнес.

Но не надо думать, что борьба эпидемией касатеся только медиков: это социальный и экономический кризис. И мы, программисты и айтишники, можем в нем себя применить.

Ниже подборка хакатонов и проектов, в которые можно вписаться pro bono, чтобы помочь в борьбе с эпидемией и ее последствиями:

Хакатоны:

Pandemic Response Hackathon пытаются лучше понять эпидемию и бороться с распростраением вируса.

CodeVsCOVID19 с очень большим количеством идей, как можно помочь.

Hack quarantine с нескольктими треками: supporting quarantined, tech and health, remote working, improving awareness and behaviour.

Задача на моделирование распространения вируса из Африки с призовым фондом.

На Kaggle:

Предлагают предсказать скорость распространения вируса, есть открытый датасет.

Сейчас выходит много медицинских статей про коронавирус, все прочитать невозможно. Есть задача помочь медикам быстрее вытаскивать из текстов важную информацию с помощью ML.

ВОЗ хотят вычислить, какие именно факторы влияют на распространение вируса и смертность.

Проекты:

COVIDарность в России помогают создавать сообщества для взаимопомощи в эпидемию. Сейчас ищут фронтенд, бэкенд разработчиков и тех, у кого есть опыт с ботами.

Folding@home занимаются численным моделированием, чтобы найти лекарство от коронавируса и им можно помочь с распределенными вычислениями.

Другие списки:

helpwithcovid.com, который делает CEO OpenAI, собирает инициативы, там можно нафильтровать себе проект по навыкам/профессии.

Coronavirus handbook: еще больше проектов и сообществ для тех, кто может прогать.

Еще один список от 8000hours с большим гуглдоком, который постоянно обновляют.

В Twitter:

Ищите инициативы по хэштегу #COVTECH.

Если встретите еще интересные ссылки, скиньте их мне, пожалуйста, в личку или в фидбэк, а я дополню список. Лайк, репост, санитайзер. 🐠
👍1
​​​​Представьте, приходите вы на новый проект, заглядываете в логи, а там вперемешку с успешными запросами на сервер вот такие сообщения:

Unexpected exception:


Что-то постоянно ломается, но молча.

Если свести к минимальному примеру то, что происходило в коде приложения, с которым я недавно начала разбираться, то получится вот такая в целом не вызывающая подозрений конструкция:

try:
raise KeyError
except Exception as e:
print(f"Unexpected exception: {e}")


Если выполнить этот пример, то и получится

Unexpected exception:


Дело в том, что есть четыре способа вывести сообщение пойманного исключения:

🐟 print(e)
🐟 print(str(e))
🐟 print(e.message)
🐟 print(repr(e))

Первые два варианта не очень информативны. Например, если попытаться обратиться к несуществующему ключу словаря (ошибка топ 1 в Python), то эти варианты выведут только название ключа.

my_dict = {}
try:
b = my_dict["bad"]
except Exception as e:
print(f"Unexpected exception: {e}")

Unexpected exception: 'bad'


Это потому, что str(e) и e выводят сообщение исключения, но не его тип. Чаще всего этого достаточно, но исключения для того и нужны, чтобы сообщать о ситуациях, которых мы не ожидаем.

Иногда пишут print(e.message). Здесь проблемы целых две: во-первых, мы по-прежнему получаем только сообщение. А во-вторых, атрибут message определен не у всех исключений. Если не снабдить наш print условием, то мы получим только новую ошибку:

AttributeError: 'KeyError' object has no attribute 'message'


А вот магический метод repr, который и нужен для того, чтобы давать максимально точное описание, все сделает отлично. Сравним:

try:
raise KeyError
except Exception as e:
print(f"Unexpected exception: {repr(e)}")

Unexpected exception: KeyError()


А в примере со словарем получилось бы

Unexpected exception: KeyError('bad')


что более явно, чем все три варианта выше 🐠

#исключения
🔥2
​​​​Хочу похвастаться: на этой неделе произошли сразу две приятные вещи.

1. После моего поста про исключения мне прислали крутой комментарий. Привожу целиком.

repr(e) -- это, конечно хорошо, но ведь есть ещё лучше, а именно:

from traceback import print_exc
...
my_dict = {}
try:
b = my_dict["bad"]
except Exception as e:
print_exc()

что выведет:

Traceback (most recent call last):
File "<pyshell#1>", line 2, in <module>
KeyError: 'bad'

и при этом программа продолжит свою работу. А если ошибку надо выводить не в stdout, то можно сделать так:

from traceback import print_exc
from io import StringIO
...
try:
b = my_dict["bad"]
except Exception:
buffer = StringIO()
print_exc(file=buffer)
out_var = buffer.getvalue()

2. Еще мне писали, что повторяли перед собеседованием Python по моему каналу. То есть, пользовались им ровно так, как я задумывала!

Вот ради таких моментов я и веду канал.

Кстати, если есть что-нибудь, о чем вы хотите прочитать, про Python, профессию или вообще, пишите @chakchurina, ответы на самые частые вопросы я публикую.
🔥1
Как устроены словари в Python, часть 1.

Представьте себе огромную библиотеку, в которой вы хотите найти «Пикник на обочине». Как это сделать?

Наивный способ — перебирать. Взять первую книгу, понять, что это не Стругацкие, поставить обратно, взять следующую, ... и так далее. В лучшем случае «Пикник на обочине» окажется в первой ячейке и мы справимся за один ход. В худшем придется перебрать все 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), но все равно очень быстрый.
🐙 Модифицировать словарь, по которому итерируешься — плохая идея. Интерпретатор может решить, что пора ресайзить хеш-таблицу и тогда старые данные переедут в новую табличку. Не стоит.

И все то же самое применимо к множествам, потому что они реализованы похожим образом.

🐙 А ещё становится понятно, что множества работают сильно быстрее списоков.

Кстати, пост не содержит совсем никаких рекомендаций, что почитать на досуге. 🐠

#словари #множества #реализация #алгоритмы #хеширование
👍2🔥1
Дублирование объектов в множестве

Пусть у нас есть сервер и его клиенты. На сервере мы хотим учитывать состояние клиентов и управлять ими. Для этого будем добавлять клиенты в множество, чтобы случайно не учесть один и тот же клиент на сервере дважды.

Создадим класс 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
Магические методы и пустые списки

Методы с двойным подчеркиванием в начале и в конце, например, __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 выбрали, потому что хотели добавить в название склизкости за счет змеи.

Семейство змей, в свою очередь, назвал питонидами французский зоолог Франсуа-Мари Доден в честь дракона, которого, согласно мифу, умертвил Аполлон у входа в Дельфийский оракул. Дракона звали Пифоном.

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

#название #начинающим
1
Дэвид Бизли, звезда Python сообщества и автор бомбических докладов про асинхронность в Python, выпустил бесплатный курс Practical Python Programming.

Курс не рассчитан на новичков, скорее на программистов, которые уже знакомы с основами Python или с другим языком. Курс не про веб-программирование, а про сам язык, так что инженерам и ученым тоже будет полезно.

Бизли сам пишет на Python 25 лет и половину этого времени преподает его, доверять можно. Очень рекомендую!
🔥1
Целочисленное деление

Как вы знаете, в Python есть два способа делить целые числа:

Оператор / при делении целого числа на целое возвращает результат типа float.

>>> 3 / 2
1.5 # float

А оператор // при делении целого на целое возвращает целое с округлением вниз, по-английски этот оператор еще называют floor division.

>>> 3 // 2
1 # int

Копалась в истории языка и узнала, что изначально деление целых чисел в Python было только целочисленное, и для него Гвидо использовал символ /. Но быстро стало понятно, что в языке, где программист не объявляет типы явно, использование такого символа неудобно и будет приводить к обилию ошибок в программах.

Поэтому часть сообщества (включая Гвидо) настаивала на том, что оператором целочисленного деления нужно выбрать символ //, а оператор деления, который возвращает тип float, должен быть /. Другие разработчики говорили, что целочисленное деление нужно писать как /, аргументируя это тем, что «научиться обращаться с целочисленным делением — это как обряд инициации для начинающих программистов», да и в C целочисленное деление пишется именно так.

Вот что Гвидо пишет об этом в своем блоге (в моем вольном переводе):

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

Я: Вот ты берешь два целых числа. Хорошо?
Она: Хорошо!
Я: Теперь ты можешь их сложить, вычесть, умножить в программе, правильно?
Она: Хм, конечно!
Я: А теперь предположим, что ты их делишь...
Она: Но в этом нет смысла! Целые числа образуют кольцо, а не поле. Ты ведь сказал, что взял эти числа из Z, верно?
Я: Ага.

Вот и все. Это точка зрения непрограммиста (с которой мне удобно согласиться). Целочисленное деление — это чушь и его не нужно писать как "/", даже если в C делают именно так;-)

Действительно, с точки зрения непрограммиста, целочисленное деление довольно странная история, ведь над целыми числами, как и над матрицами, нет деления в принципе!

Источники: [1], [2].

Кстати, я сейчас готовлю курс по пайтон для начинающих (не то чтобы я считала, что на рынке мало курсов, но я просто люблю учить людей). Как считаете, стоит добавить этот фрагмент в курс, или лучше вырезать?
👍1
Работа с JSON

Хотела собрать для менти ссылок по работе с JSON, но не нашла, чтобы в одном месте последовательно, исчерпывающе и без воды рассказали бы все самое важное, что питонисту нужно знать о работе с этим форматом.

Поэтому сделала лонгрид по JSON'у сама и делюсь с вами! Статью в PDF можно посмотреть на моем Patreon'e, она бесплатная. Рассчитана на уровень джуниоров и стажеров. В канал выложить не могу, потому что слишком много текста, а в тексте картинки, схемы и даже один мем!

Из головных болей: не получилось сверстать так идеально, как хотелось. Начала с LaTeX, поняла, что верстается долго, перешла в markdown, но там некрасиво легли картинки. Наконец, сделала в Notion и все равно недовольна. Дайте знать, если умеете красиво верстать без боли и адских страданий или можете рассказать, на какой платформе вам удобнее читать лонгриды.

🐠

Один из отзывов: Прочитал твою статью про json! Восторг! Ты так хорошо и спокойно объясняешь! Ты смогла мои обрывочные знания систематизировать.

Спасибо вам за такие хорошие слова🤍 Стараюсь для вас.
🔥1
Открываю курс по Python.

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

Курс подойдет вам если вы:
🐟 только начинаете программировать,
🐟 уже пытались изучать основы, но в знаниях хочется навести порядок.

О курсе:
🐟 Теория и задачи ждут вас на платформе Stepik.
🐟 Сейчас курс продается за 2700 рублей и можно пройти первые 5 модулей. Остальные 7 модулей я открою для прохождения в течение 7 недель.
🐟 Я внимательно слежу за комментариями и буду обновлять и дополнять материал там, где это будет нужно.
🐟 Когда я открою последний модуль, цена вырастет в полтора раза. Так что предлагаю заинтересованным опередить меня!

Научиться писать на Python под моим наблюдением можно здесь.
👍1
Блок 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
Печать списков

Если вдруг на собеседовании вам понадобится вывести список (или множество) чисел на печать одной строкой, то вот изящный способ это сделать:
 
>>> 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
Резюме для разбора можно прислать мне или Алисе.

Ставьте огонек, если собираетесь прийти, чтобы я понимала, сколько нас будет🔥
👍1