PyWay – гуру Python 🐉
1.01K subscribers
22 photos
1 video
2 files
153 links
Ваш путь в глубины Python. Узнай все секреты и фишки у нас! Если хотите сотрудничать – пишите @account1242 (условия @pyway_ads)
Download Telegram
Оставить в списке только уникальные значения без повторов?
(иногда спрашивают на собеседовании)

В этом списке есть повторы:
>>> x = [1, 2, 3, 2, 4, 4, 5, 2]

А теперь нет повторов:
>>> list(set(x))
[1, 2, 3, 4, 5]


Дело в том, что тип данных set (множество) повторов не допускает. Мы делаем из списка - множество, а из множества снова - список.

Один нюанс: порядок следования элементов после этого не гарантирован.

from collections import OrderedDict
OrderedDict.fromkeys(l).keys()


А теперь и порядок будет сохранен, если мы для наших целей воспользуемся ключами от OrderedDict (упорядоченный словарь).
🧠 Искуственный интеллект и нейронные сети сейчам на гребне хайпа. Казалось бы, куда нам до такой сложной темы? Однако оказывается, что простейшую нейросеть и алгоритм ее обучения можно написать, усложившись всего в 11 строк кода на Python!

Рекомендую к прочтению эту популярную статью: "Нейросеть в 11 строчек на Python".
Channel name was changed to «PyWay – гуру Питона»
🤔 Добавь щепотку многозначительности, задумчивости и недосказанности в свой код на Python с помощью троеточий...

Троеточие. Оно же многоточие, если по правилам, как утверждала наша учительница русского языка в школе и ставила нам двойки. 👩‍💼2️⃣ Что тут сказать? Для некоторых все, что больше двух – уже много.

Есть в питоне такая вещь:

>>> ...
Ellipsis
>>> type(...)
<class 'ellipsis'>


Что это и как это применить?

Читай подробнее в моей новой авторской статье...
Как найти все файлы с определенным расширением?
В модуле glob (начиная с Python 3.4) можно использовать ** для этих целей.

Например, найдем в каталоге photos все картинки jpg даже если они в подкаталогах:

import glob

for filename in glob.iglob('photos/**/*.jpg', recursive=True):
print(filename)


В более старых версиях:

import fnmatch
import os

matches = []
for root, dirnames, filenames in os.walk('photos'):
for filename in fnmatch.filter(filenames, '*.jpg'):
matches.append(os.path.join(root, filename))
🎮 Делать игры – это интересно!
Однако, многие люди часто приходят на форумы игроделов и предлагают там запилить сразу нового Ведькама онлайн с элементами GTA, хотя сами до этого никаких игр не делали. 🤫 Стандартный ответ от постояльцев форумов – иди сделай хотя бы "Змейку". 🐍 А между прочим змейку на Питоне (какой каламбур) можно сделать буквально за час, уложившись в пару сотен строк кода.

Нам поможет библиотека pygame (Установка: pip install pygame).

Вот, например, я нашел в интернете такую реализацию змейки:

https://pycoder.ru/snake-pygame/

А ведь некоторые укладываются в 35 строк (а то и меньше):

https://gist.github.com/tirinox/cac592b3d3d2e9112540a5ddbcfadb3c
Почему моя многопоточная программа на Python выполняется медленнее, чем однопоточный вариант? Как это вообще возможно? 😱

Если вы задавали когда-то себе такой вопрос или вам его задавали на собеседовании, но вы не ответили, то самое время узнать про GIL (global interpreter lock, "джил", если произносить на русском).

Концепция GIL по-русски на Вики: https://ru.wikipedia.org/wiki/Global_Interpreter_Lock:

☝️GIL является самым простым способом избежать конфликтов при одновременном обращении разных потоков к одним и тем же участкам памяти. Когда один поток захватывает его, GIL, работая по принципу мьютекса, блокирует остальные. Нет параллельных потоков — нет конфликтов при обращении к разделяемым объектам. Очерёдность выполнения потоков определяет интерпретатор в зависимости от реализации, переключение между потоками может происходить: когда активный поток пытается осуществить ввод-вывод, по исчерпании лимита выполненных инструкций либо по таймеру.

👨‍💻GIL существует уже давно и никуда не делся. В 2018 про него спросят практически на любом собеседовании на должность Python программиста.

📰На Хабре вы найдете более глубокое объяснение принципа работы GIL: https://habr.com/post/84629/
Индексы в Python

В моей новой статье вы узнаете, как можно пользоваться отрицательными индексами для списков и кортежей. 🤨 Узнаете, что такое срезы. 🍕 И о том, как обращаться к вашим собственным классам по индексу. 💪 Эти поистине мощные возможности языка должен знать каждый питонист!

http://tirinox.ru/python-indexing/
В рейтинге языков программирования PYPL Python по-прежнему лидирует. Он обогнал PHP примерно в 2015 году. Рейтинг составляется на базе частоты поисковых запросов в Google: http://pypl.github.io/PYPL.html
[#новичкам] 👩‍🎓 Если вам надо пробежаться по списку и нужно знать номер элемента в списке, то не обязательно заводить отдельную переменную и инкрементировать ее на каждом шаге цикла. Достаточно воспользоваться встроенной функцией enumerate:

a = ['Hello', 'world', '!']
for i, x in enumerate(a):
# в переменной i будет номер, а в x - элемент списка a
print '{}: {}'.format(i, x)

Вывод:
0: Hello
1: world
2: !


🎈 Нас уже больше 100 человек! Ура! 🎈
[#новичкам] 👩‍🎓 Уплощение списков (flattenning lists)

Пусть есть вложенные списки (список списков):
>>> a = [[1, 2], [3, 4], [5, 6]]

Можно расплющить их через составление цепочки:
>>> import itertools
>>> list(itertools.chain.from_iterable(a))
[1, 2, 3, 4, 5, 6]


Коротко через сумму sum ([] – здесь начальное слагаемое суммы, а сумма двух списков – список из элементов первого, а потом второго списка):
>>> sum(a, [])
[1, 2, 3, 4, 5, 6]


Через двойной обход:
>>> [x for l in a for x in l]
[1, 2, 3, 4, 5, 6]


Если список списков списков (тройная вложенность):
>>> a = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
>>> [x for l1 in a for l2 in l1 for x in l2]
[1, 2, 3, 4, 5, 6, 7, 8]


Если уровень вложенности или структура не известны заранее, тогда общий случай:
>>> a = [1, 2, [3, 4], [[5, 6], [7, 8]]]
>>> flatten = lambda x: [y for l in x for y in flatten(l)] if type(x) is list else [x]
>>> flatten(a)
[1, 2, 3, 4, 5, 6, 7, 8]
Числа с плавающей точкой

Многих новичков (и не очень новичков) может фрустрировать тот факт, что:

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17


😱 Нет, ваш Python не сломан, так и должно быть. Много слов уже сказано про представление чисел с точкой в компьютерах. Большинство наших вычислений производится согласно стандарту IEEE754 (👉читайте подбронее https://habr.com/post/112953/).

Если коротко, то числа в компьютере квантированы, то есть если упрощенно, они не непрерывны. Факт: числа 0.3 для компьютера не существует, зато есть самое ближайшее к нему число (3 - 5.551115123125783e-17).

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

>>> 0.3 == 0.3
True
>>> (0.1 + 0.1 + 0.1) == 0.3
False


Лучше сравнивать их приблизительно (модуль разницы с неким малым числом):

>>> def floats_equal(x, y, eps=1e-10): return abs(x - y) < eps
>>> floats_equal( 0.1 + 0.1 + 0.1, 0.3 )
True


💸 Если ваше приложение связано с подсчетом денег, точность всегда критична, иначе ваш баланс не сойдется. Для этого давно придуман модуль decimal (https://docs.python.org/3.6/library/decimal.html). В нем есть класс Decimal – фактически он представляет собой число с фиксированной точкой.

>>> from decimal import *
>>> Decimal(0.1)+Decimal(0.1)+Decimal(0.1)-Decimal(0.3)
Decimal('1.11022302E-17')


😤 Что за дела? Опять тоже самое! Дело в том, что нельзя получить "качественный" Decimal из обычного числа (мы помним, что 0.3 – не существует и будет подобрано ближайшее).

💡 Фишка в том, что нужно сначала преобразовать число в строку (str), а потом передать в Decimal. Тогда он будет явно знать какое число из реального мира мы хотим сохранить:

>>> Decimal(str(0.1)) + Decimal(str(0.1)) + Decimal(str(0.1)) - Decimal(str(0.3))
Decimal('0.0')
[📕 Библиотеки ] emoji (pip install emoji) Любителям Эмодзи. Эта библиотека позволяет вам получать юникодовые Эмодзи смайлики по их ASCII псевдонимам и наоборот. Пример:

>> import emoji
>> print(emoji.emojize('Python is :thumbs_up:'))
Python is
👍
>> print(emoji.emojize('Python is :thumbsup:', use_aliases=True))
Python is
👍
>> print(emoji.demojize('Python is
👍'))
Python is :thumbs_up:


Список псевдонимов: https://www.webpagefx.com/tools/emoji-cheat-sheet/
🤦‍♂️Python на железе? Да ну, что за бред!

Известно, что Python является высокоуровневым языком, с ООП, с элементами функционального и мета программирования, асинхронной конкуретной моделью. Однако, оказывается, что Python можно применять даже на микроконтроллерах. Реализация MicroPython хоть и не настолько полна, как CPython, однако так же удобна и понятна, и при этом – чрезвычайно мощна.

🔩Посмотрите, как легко начать разрабатывать на Python под ESP8266 (малюсенькая плата на ARM с Wi-Fi):

👉Python для микроконтроллеров. Учимся программировать одноплатные компьютеры на языке высокого уровня

Кстати, ESP8266 можно заказать на Ali (от 100 руб.): https://goo.gl/j5mqsV
f-строки
📝 В Python существуют целых 5 стандартных способов форматировать строки (+, %, Template, str.format, f-строки).

f-строки появились в Python 3.6 и являются наиболее современным и гибким способом форматирования строк (еще этот способ называют интерполяцией строк). Они позволяют использовать значения любых переменных из окружения строки, а также даже выполнять некоторый код.

Синтаксически мы просто добавляем букву f (или F) перед открывающией кавычкой строки. Внутри строки в фигурных скобках мы можем писать почти любые выражения на Python, использовать переменные и функции; результат этого выражения будет будет подставлен на место фигурных скобок.

📎 Примеры:

>>> x, y = 5, 1/3

>>> f'x = {x} and y = {y}'
'x = 5 and y = 0.3333333333333333'

>>> f'x = {x} and y = {y:.5}; so x + y = {(x + y):.5}'
'x = 5 and y = 0.33333; so x + y = 5.3333'

>>> f'y = {round(y, 2)}'
'y = 0.33'


f-строки – это не только модно и удобно, но и быстро. Тесты показывают, что они на четверть быстрее str.format.

Я нашел для вас статью, где вы увидите больше примеров f-строк 👈
[📕 Библиотеки ] Pympler (pip install pympler)
Эта библиотка поможет вам профилировать использование памяти в программах на Python. Наоболее часто она используется для нахождения реального размера объектов в байтах.

📎 Примеры:

>>> from pympler.asizeof import asizeof
>>> asizeof(10)
32
>>> asizeof("Hello world")
64
>>> asizeof({})
240
>>> asizeof({"foo":"bar"})
352
>>> class Baz: ...
...
>>> asizeof(Baz())
168

В отличие от системной sys.getsizeof, asizeof – считает размер сложных объектов рекурсивно.

https://pythonhosted.org/Pympler/
Дизассемблирование Python (dis)

🚗 Программа Python выболняется на виртуальной машине. Во время интерпретации высокоуровненые команды превращаются в байт-код (элементарные команды для виртуальной машины). С модулем dis мы можем узнать какой именно байт-код был сгенерирован. Это часто нужно для глубокой оптимизации кода.

📎 Примеры:

>>> import dis

Можно дизассмблировать код из строки:

>>> dis.dis("print(1)")
1 0 LOAD_NAME 0 (print)
2 LOAD_CONST 0 (1)
4 CALL_FUNCTION 1
6 RETURN_VALUE


Или из функции:

>>> def foo(x, y): return x + 2 * y
...
>>> dis.dis(foo)
1 0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (2)
4 LOAD_FAST 1 (y)
6 BINARY_MULTIPLY
8 BINARY_ADD
10 RETURN_VALUE


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

👉Документация на dis

P.S. Все вышеперечисленное относится к реализации CPython, в других реализациях, вероятно, будут отличия.