Чувак сжал 2,87 ГБ данных до 8,9 МБ (!) с помощью своего кастомного компрессора данных :D
Там было 21k JSON-файлов с данными о крикетных матчах, он использовал их структуру и сжал это до ~42,46 МБ
Максимум, что смог
Потом он скомбинировал свой компрессор +
Это ЧИСТАЯ случайность, дальше сжать уже просто нельзя.
Ему пришлось почитать про энтропию Шеннона и алгоритмическое сжатие данных
Полный разбор в GitHub-репозитории😎
👉 @PythonPortal
Там было 21k JSON-файлов с данными о крикетных матчах, он использовал их структуру и сжал это до ~42,46 МБ
Максимум, что смог
gzip, это ~53 МБ, а 7z ~45 МБ.Потом он скомбинировал свой компрессор +
7z и ужал до 8,9 МБЭто ЧИСТАЯ случайность, дальше сжать уже просто нельзя.
Ему пришлось почитать про энтропию Шеннона и алгоритмическое сжатие данных
Полный разбор в GitHub-репозитории
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯68🔥11❤6🏆2👍1🤔1
Немного базы Python. День 5. Сортировка списка по убыванию
Метод
Чтобы
У метода
Помните:
Метод
Если вы попробуете создать новый объект с помощью
У метода
Этот параметр используется для передачи функции, которая задает критерий сортировки элементов списка.
В примере ниже у нас список кортежей, и мы хотим отсортировать его по возрасту студента. Используя параметр
Метод
Если у двух элементов одинаковый ключ сортировки, их исходный порядок сохраняется. Например, если у
Как видно, порядок элементов
👉 @PythonPortal #100daysofpython
Метод
sort() сортирует список по возрастанию (по умолчанию).Чтобы
sort() работал, элементы списка должны быть одного типа. Нельзя сортировать список со смешанными типами данных, например числа и строки.У метода
sort() есть параметр reverse; чтобы отсортировать список по убыванию, установите reverse=True.list1 = [2, 5, 6, 8, 1, 8, 9, 11]
list1.sort(reverse=True)
print(list1)
# [11, 9, 8, 8, 6, 5, 2, 1]
Помните:
sort() это строго метод списка (list). Его нельзя использовать для сортировки set, tuple, string или dictionary.Метод
sort() не возвращает новый список; он сортирует существующий список на месте (in place).Если вы попробуете создать новый объект с помощью
sort(), он вернет None. Пример ниже:list1 = [2, 5, 6, 8, 1, 8, 9, 11]
list2 = list1.sort(reverse=True)
print(list2)
# None
У метода
sort() есть необязательный параметр key, который позволяет настроить поведение сортировки.Этот параметр используется для передачи функции, которая задает критерий сортировки элементов списка.
В примере ниже у нас список кортежей, и мы хотим отсортировать его по возрасту студента. Используя параметр
key вместе с lambda-функцией, можно реализовать такую кастомную сортировку. См. ниже:students = [
("Alice", 22),
("Bob", 20),
("Charlie", 24)
]
# Сортируем студентов по возрасту, используя lambda-функцию как key
students.sort(key=lambda students: students[1])
print(students)
# [('Bob', 20), ('Alice', 22), ('Charlie', 24)]
Метод
sort() является стабильным (stable), то есть сохраняет относительный порядок равных элементов в отсортированном списке.Если у двух элементов одинаковый ключ сортировки, их исходный порядок сохраняется. Например, если у
"Alice" и "Bob" одинаковый возраст, их порядок останется прежним. Это и называется стабильной сортировкой (stable sorting). См. пример:students = [
("Alice", 22),
("Bob", 22),
("Charlie", 24)
]
# Сортируем студентов по возрасту, используя lambda-функцию как key
students.sort(key=lambda students: students[1])
print(students)
# [('Alice', 22), ('Bob', 22), ('Charlie', 24)]
Как видно, порядок элементов
"Alice" и "Bob" не изменился, потому что у них одинаковый возраст.Please open Telegram to view this post
VIEW IN TELEGRAM
❤24👍11
Перестаньте использовать
В Python, когда вы пишете:
вы не проверяете напрямую, является ли
Да, во многих случаях результат будет таким же, как у кода:
Но поведение у этих двух вариантов разное, и эта разница важна.
Когда вы используете:
Python вызывает метод
Если
Пример:
Здесь видно, что
Из этого следует, что при использовании
С другой стороны, когда вы пишете:
вы используете оператор
Оператор
❤️ Поэтому всегда рекомендуется, и это best practice, использовать
👉 @PythonPortal
if obj == None, используйте if obj is NoneВ Python, когда вы пишете:
obj == None
вы не проверяете напрямую, является ли
obj значением None. Вместо этого вы спрашиваете, равен ли объект None.Да, во многих случаях результат будет таким же, как у кода:
obj is None
Но поведение у этих двух вариантов разное, и эта разница важна.
Когда вы используете:
obj == None
Python вызывает метод
__eq__ у объекта. То есть сам объект решает, что значит "равен None". А этот метод можно переопределить.Если
obj это экземпляр класса, в котором __eq__ реализован так, что при сравнении с None возвращается True (даже если объект на самом деле не None), тогда obj == None может ошибочно дать True.Пример:
class Weird:
def __eq__(self, other):
return True # Всегда утверждает, что равен
obj = Weird()
print(obj == None) # True
print(obj is None) # False
Здесь видно, что
obj == None возвращает True из-за кастомного поведения оператора __eq__ в классе.Из этого следует, что при использовании
obj == None результат не всегда предсказуем.С другой стороны, когда вы пишете:
obj is None
вы используете оператор
is, который нельзя переопределить. Это значит, что результат всегда будет одинаковым и предсказуемым.Оператор
is проверяет идентичность объектов, то есть указывают ли две ссылки на один и тот же объект. Поскольку None это singleton (единственный экземпляр), obj is None это правильный и самый эффективный способ такой проверки.obj is None вместо obj == None ради предсказуемости и эффективности.Please open Telegram to view this post
VIEW IN TELEGRAM
👍40❤10🔥3
Немного базы Python. День 6 - Обмен значениями переменных
В Python можно менять местами переменные после того, как им уже присвоены объекты. Ниже мы сначала присваиваем
Также можно использовать оператор XOR (exclusive or), чтобы поменять переменные местами. Это трехшаговый метод. В примере ниже мы меняем местами значения
Также можно использовать арифметические операции (сложение и вычитание), чтобы поменять переменные местами без временной переменной. Однако этот метод рекомендуется для обмена переменных числовых типов данных. Вот пример:
В результате этих арифметических операций значения
Этот способ обмена переменных без временной переменной основан на том, что когда вы прибавляете или вычитаете значение одной переменной из другой, можно эффективно обменять их значения без необходимости в дополнительном хранилище.
👉 @PythonPortal #100daysofpython
В Python можно менять местами переменные после того, как им уже присвоены объекты. Ниже мы сначала присваиваем
20 переменной x и 30 переменной y, а потом меняем их местами: x становится 30, а y становится 20. Этот способ называется упаковкой и распаковкой кортежа (tuple packing/unpacking).x, y = 20, 30
x, y = y, x
print('x is: ', x)
print('y is: ', y)
x is 30
y is 20
Также можно использовать оператор XOR (exclusive or), чтобы поменять переменные местами. Это трехшаговый метод. В примере ниже мы меняем местами значения
x и y.x = 20
y = 30
# шаг первый
x ^= y
# шаг второй
y ^= x
# шаг третий
x ^= y
print(f'x is: {x}')
print(f'y is: {y}')
x is: 30
y is: 20
Также можно использовать арифметические операции (сложение и вычитание), чтобы поменять переменные местами без временной переменной. Однако этот метод рекомендуется для обмена переменных числовых типов данных. Вот пример:
# Используем арифметические операции
x = 5
y = 10
x = x + y
y = x - y
x = x - y
print("After swapping:")
print("x =", x)
print("y =", y)
After swapping:
x = 10
y = 5
В результате этих арифметических операций значения
x и y были фактически поменяны местами. После обмена x содержит исходное значение y (10), а y содержит исходное значение x (5).Этот способ обмена переменных без временной переменной основан на том, что когда вы прибавляете или вычитаете значение одной переменной из другой, можно эффективно обменять их значения без необходимости в дополнительном хранилище.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤5🤔4
Алгоритмы оптимизации от MIT:
https://drive.google.com/file/d/1Rx7MAekKZbyNVc5B2MNfR0HXXIEJCksp/view
👉 @PythonPortal
https://drive.google.com/file/d/1Rx7MAekKZbyNVc5B2MNfR0HXXIEJCksp/view
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Немного базы Python. День 7. Подсчет количества вхождений элемента
Если тебе нужно узнать, сколько раз элемент встречается в итерируемой коллекции, можно использовать класс
Вывод:
Еще один способ сделать это — обычный цикл
Вывод:
Списки и другие итерируемые структуры данных в Python имеют встроенный метод
Вывод:
👉 @PythonPortal #100daysofpython
Если тебе нужно узнать, сколько раз элемент встречается в итерируемой коллекции, можно использовать класс
Counter из модуля collections. Counter() вернет словарь с тем, сколько раз каждый элемент встречается в последовательности. Допустим, мы хотим узнать, сколько раз имя Peter встречается в следующем списке. Можно использовать Counter(). См. ниже:from collections import Counter
list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
count_peter = Counter(list1).get("Peter")
print(f'The name "Peter" appears in the list '
f'{count_peter} times.')
Вывод:
The name "Peter" appears in the list 2 times.
Еще один способ сделать это — обычный цикл
for. Мы заводим переменную-счетчик и увеличиваем ее на 1 каждый раз, когда находим имя Peter в последовательности. Это наивный способ. См. ниже:list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
# Create a count variable
count = 0
for name in list1:
if name == 'Peter':
count +=1
print(f'The name "Peter" appears in the list'
f' {count} times.')
Вывод:
The name "Peter" appears in the list 2 times.
Списки и другие итерируемые структуры данных в Python имеют встроенный метод
count(), который позволяет посчитать количество вхождений конкретного элемента. Мы можем использовать count(), чтобы посчитать, сколько раз Peter встречается в списке.list1 = ['John', 'Kelly', 'Peter', 'Moses', 'Peter']
print(f'The name "Peter" appears in the list '
f'{list1.count("Peter")} times.')
Вывод:
The name "Peter" appears in the list 2 times.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤19👍7🔥5👀2
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17😢4👍3
Please open Telegram to view this post
VIEW IN TELEGRAM
😁45🤣19❤6
Немного базы Python. День 8 - Сделать вложенный список плоским
Я покажу вам три (3) способа, как можно развернуть двумерный список. В первом методе используется цикл
⚙️ С помощью цикла for:
Для этого метода мы используем вложенный цикл
⚙️ С помощью модуля itertools:
Функцию
Вы можете увидеть, что вложенный цикл был развернут.
⚙️ С помощью list comprehension
Если вы не хотите импортировать
List comprehension хорошо подходит для умеренно вложенных списков. Для глубоко вложенных списков он не подходит, так как код становится хуже читаемым.
⚙️ С помощью генераторной функции
Можно создать генераторную функцию, которая делает
Метод с генератором подходит для разворачивания больших или глубоко вложенных списков. Это потому, что генераторы экономно расходуют память.
👉 @PythonPortal #100daysofpython
Я покажу вам три (3) способа, как можно развернуть двумерный список. В первом методе используется цикл
for, во втором используется модуль itertools, а в третьем используется списковое включение (list comprehension).Для этого метода мы используем вложенный цикл
for. Внешний цикл проходит по внутренним спискам, а внутренний цикл обращается к элементам во внутренних списках.# In [19]:
list1 = [[1, 2, 3],[4, 5, 6]]
newlist = []
for list2 in list1:
for j in list2:
newlist.append(j)
print(newlist)
[1, 2, 3, 4, 5, 6]
Функцию
itertools.chain.from_iterable() из модуля itertools можно использовать, чтобы развернуть вложенный список. Этот метод может не подойти для списков с глубокой вложенностью.# In [20]:
import itertools
list1 = [[1, 2, 3],[4, 5, 6]]
flat_list = list(itertools.chain.from_iterable(list1))
print(flat_list)
[1, 2, 3, 4, 5, 6]
Вы можете увидеть, что вложенный цикл был развернут.
Если вы не хотите импортировать
itertools или писать обычный цикл for, можно просто использовать list comprehension.# In [21]:
list1 = [[1, 2, 3], [4, 5, 6]]
flat_list = [i for j in list1 for i in j]
print(flat_list)
[1, 2, 3, 4, 5, 6]
List comprehension хорошо подходит для умеренно вложенных списков. Для глубоко вложенных списков он не подходит, так как код становится хуже читаемым.
Можно создать генераторную функцию, которая делает
yield элементов из вложенного списка, а затем преобразовать генератор в список.# In [22]:
def flatten_generator(nested_list):
for sublist in nested_list:
for item in sublist:
yield item
list1 = [[1, 2, 3], [4, 5, 6]]
flat_list = list(flatten_generator(list1))
flat_list
Out[22]: [1, 2, 3, 4, 5, 6]
Метод с генератором подходит для разворачивания больших или глубоко вложенных списков. Это потому, что генераторы экономно расходуют память.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍9
Python-совет по дизайну: используй
Люди обычно ожидают, что всё, что выглядит как доступ к атрибуту, работает быстро.
Не хочется же жать Ctrl-C на чтении атрибута, потому что там спрятан расчёт уровня Deep Thought на 7,5 миллионов лет:
👉 @PythonPortal
@property только для O(1) операцийЛюди обычно ожидают, что всё, что выглядит как доступ к атрибуту, работает быстро.
Не хочется же жать Ctrl-C на чтении атрибута, потому что там спрятан расчёт уровня Deep Thought на 7,5 миллионов лет:
>>> life.meaning
42
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔11❤6😁3
Немного базы Python. День 9. Индекс наибольшего числа
Есть несколько способов найти индекс самого большого числа в списках.
▪️ Функция
Можно использовать метод
▪️
В коде ниже функция
▪️ Списковое включение с функцией
В коде ниже мы используем списковое включение вместе с
Вывод показывает, что самое большое число находится по индексу 3.
👉 @PythonPortal #100daysofpython
Есть несколько способов найти индекс самого большого числа в списках.
max() и метод index()Можно использовать метод
index() вместе с функцией max(), чтобы получить индекс наибольшего числа в списке. В этом примере мы с помощью max() находим самое большое число в списке и передаем его в index() как аргумент. Метод index() вернет индекс первого вхождения наибольшего числа.In [23]: my_list = [12, 45, 67, 89, 34, 67, 13]
largest_number_index = my_list.index(max(my_list))
largest_number_index
Out[23]: 3
max() и enumerate()В коде ниже функция
max() принимает список и lambda-функцию в качестве аргументов. Мы добавляем enumerate() к списку, чтобы она могла вернуть и число из списка, и его индекс (кортеж). Параметр start в enumerate() задаем так, чтобы нумерация начиналась с позиции 0. lambda-функция используется, чтобы найти максимальное значение по второму элементу каждого кортежа, то есть по значению из my_list.In [24]: my_list = [12, 45, 67, 89, 34, 67, 13]
max_num = max(enumerate(my_list, start=0),
key = lambda x: x[1])
print('Индекс наибольшего числа:',
max_num[0])
Индекс наибольшего числа: 3
enumerate()В коде ниже мы используем списковое включение вместе с
enumerate(), чтобы найти индекс самого большого числа в списке. Создаем переменную max_value - в ней хранится максимальное значение из списка. Дальше с помощью enumerate() находим индекс(ы), где значение совпадает с этим максимумом.In [25]: my_list = [12, 45, 67, 89, 34, 67, 13]
max_value = max(my_list)
max_indices = [idx for idx, val in enumerate(my_list) if val == max_value]
max_indices
Out[25]: [3]
Вывод показывает, что самое большое число находится по индексу 3.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍7😁2
Всегда пиши код так, будто тот, кому потом его поддерживать, это буйный психопат, который знает, где ты живешь.
— Аноним
Знаете какие-нибудь забавные имена переменных?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤25😁12🤣6🤔1
Этот Python-фреймворк может скрейпить ЛЮБОЙ сайт и вытаскивать структурированные данные за считанные минуты.
Называется Scrapy. Он краулит сайты и извлекает структурированные данные целиком с твоей машины.
Никаких счетов за SaaS-скрейпинг. Никаких лимитов облачных API. Никакие данные не уходят за пределы твоей инфраструктуры.
Работает на самом “боевом” краулинг-движке в Python: 59K звёзд и 15+ лет продакшен-использования.
→ Описал spider один раз
→ Получил чистые структурированные данные
→ Масштабируешься до миллионов страниц
→ Экспорт в JSON, CSV, XML в один момент
Всё локально. Ноль зависимости от облака.
Но это не просто скрипт для парсинга.
Это полноценный фреймворк для извлечения данных:
→ Асинхронная архитектура для параллельного краулинга в масштабе
→ Встроенные middleware для прокси, ретраев и rate limiting
→ CSS и XPath селекторы без лишнего бойлерплейта
→ Подключаемые pipelines для чистки, дедупликации и сохранения
→ 54 800+ продакшен-проектов уже завязаны на него
100% open source. Лицензия BSD-3.
Работает на macOS, Windows и Linux уже сейчас.
Хочешь сделать хорошо, сделай сам, вместо облачных сервисов запускаешь всё у себя.🪖 🪖
100% опенсорс
👉 @PythonPortal
Называется Scrapy. Он краулит сайты и извлекает структурированные данные целиком с твоей машины.
Никаких счетов за SaaS-скрейпинг. Никаких лимитов облачных API. Никакие данные не уходят за пределы твоей инфраструктуры.
Работает на самом “боевом” краулинг-движке в Python: 59K звёзд и 15+ лет продакшен-использования.
→ Описал spider один раз
→ Получил чистые структурированные данные
→ Масштабируешься до миллионов страниц
→ Экспорт в JSON, CSV, XML в один момент
Всё локально. Ноль зависимости от облака.
Но это не просто скрипт для парсинга.
Это полноценный фреймворк для извлечения данных:
→ Асинхронная архитектура для параллельного краулинга в масштабе
→ Встроенные middleware для прокси, ретраев и rate limiting
→ CSS и XPath селекторы без лишнего бойлерплейта
→ Подключаемые pipelines для чистки, дедупликации и сохранения
→ 54 800+ продакшен-проектов уже завязаны на него
100% open source. Лицензия BSD-3.
Работает на macOS, Windows и Linux уже сейчас.
Хочешь сделать хорошо, сделай сам, вместо облачных сервисов запускаешь всё у себя.
100% опенсорс
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍4
Немного базы Python. День 10 - Абсолютное значение (модуль) числа
Допустим, у тебя есть отрицательное число и ты хочешь получить его абсолютное значение. Для этого можно использовать функцию
Также
➡️ Использование модуля math
Если тебе нужны более продвинутые математические функции, можно использовать
➡️ Использование lambda-функции
Можно также использовать
👉 @PythonPortal #100daysofpython
Допустим, у тебя есть отрицательное число и ты хочешь получить его абсолютное значение. Для этого можно использовать функцию
abs(). Функция abs() возвращает абсолютное значение любого числа (положительного, отрицательного и комплексного). Ниже показано, как получить список абсолютных значений из списка, где есть и отрицательные, и положительные числа. Используем list comprehension.list1 = [-12, -45, -67, -89, 34, 67, -13]
print([abs(num) for num in list1])
[12, 45, 67, 89, 34, 67, 13]
Также
abs() можно применять к числу с плавающей точкой, и она вернет абсолютное значение. Смотри ниже:num = -23.12
print(abs(num))
23.12
Если тебе нужны более продвинутые математические функции, можно использовать
fabs() из модуля math. Эта функция всегда возвращает float.import math
num = -23.12
absolute_value = math.fabs(num)
absolute_value
23.12
Можно также использовать
lambda, чтобы превратить отрицательное число в модуль. Код ниже проверяет, меньше ли x нуля (то есть отрицательное ли значение). Если да, возвращает -x, по сути убирая минус и делая число положительным. Если x не отрицательное (больше или равно 0), возвращает x как есть.num = -23.12
absolute_value = (lambda x: -x if x < 0 else x)(num)
absolute_value
23.12
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍3
Немного базы Python. День 11 - Добавление разделителя тысяч
Если вы работаете с большими числами и хотите добавить разделитель, чтобы их было проще читать, есть несколько способов это сделать. Вот некоторые из них:
▪️ Использование функции
List comprehension проходит по каждому элементу (числу) в
Вывод печатает
▪️ Использование f-строк
Также можно использовать f-строки, чтобы добавить разделители тысяч. Обратите внимание ниже: вместо запятой (
Заметили, что в обоих случаях мы используем list comprehension, чтобы добавить разделитель? Крутая штука, правда?😉
▪️ Использование модуля
Модуль
Этот код проходит по каждому числу в
👉 @PythonPortal #100daysofpython
Если вы работаете с большими числами и хотите добавить разделитель, чтобы их было проще читать, есть несколько способов это сделать. Вот некоторые из них:
formatList comprehension проходит по каждому элементу (числу) в
my_list. Для каждого числа он форматирует его в строку с разделителями тысяч запятыми, используя строку формата '{:,}'.format(num).my_list = [10898767, 9876780, 9908763]
new_list = ['{:,}'.format(num) for num in my_list]
print(new_list)
# ['10,898,767', '9,876,780', '9,908,763']
Вывод печатает
new_list, который содержит отформатированные строки с разделителями запятыми.Также можно использовать f-строки, чтобы добавить разделители тысяч. Обратите внимание ниже: вместо запятой (
,) как разделителя мы используем подчёркивание (_).my_list = [10898767, 9876780, 9908763]
new_list = [f"{num:_}" for num in my_list]
print(new_list)
# ['10_898_767', '9_876_780', '9_908_763']
Заметили, что в обоих случаях мы используем list comprehension, чтобы добавить разделитель? Крутая штука, правда?
localeМодуль
locale даёт способ форматировать числа с разделителями тысяч в соответствии с текущими настройками локали. Вы можете выставить нужную локаль и использовать метод locale.format_string(). Вот как это выглядит на практике:import locale
my_list = [10898767, 9876780, 9908763]
formatted_list = []
for num in my_list:
# Set the locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
formatted_list.append(locale.format_string("%d", num, grouping=True))
print(formatted_list)
Этот код проходит по каждому числу в
my_list через цикл for. Он задаёт нужную локаль 'en_US.UTF-8' с помощью locale.setlocale(locale.LC_ALL, 'en_US.UTF-8'). Это выставляет локаль на США с кодировкой UTF-8, где для тысяч используются запятые. Дальше locale.format_string('%d', num, grouping=True) форматирует число (num) в строку с разделителями тысяч. Спецификатор формата '%d' означает, что число нужно форматировать как целое, а grouping=True указывает, что разделители тысяч должны быть включены.Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍8