TGINSIGHT CHAT
Python Заметки
@pythonotes
EducationИнтересные заметки и обучающие материалы по Python Контакт: @paulwinex ⚠️ Рекламу на канале не делаю!⚠️ Хештеги для поиска: #tricks #libs #pep #basic #regex #qt #django #2to3 #source #offtop
Неодамнешни објави
Страница 29 од 32 · 384 објави
Објавено 12 мар.
Начиная с версии Python 3.7 появился встроенный профайлер времени импорта модуля. Чтобы его активировать достаточно к запуску интерпретатора добавить аргумент -X importtime python3 -X importtime Теперь каждый загруженный модуль будет показывать время своей загрузки, а так же время загрузки вложенных модулей. Если нет возможности добавить аргумент в команду, то используйте переменную PYTHONPROFILEIMPORTTIME, результат аналогичен Linux: export PYTHONPROFILEIMPORTTIME=1 Windows set PYTHONPROFILEIMPORTTIME=1 #tricks
Hashtags
Објавено 10 мар.
Обычная практика удаления одинаковых значений из списка с помощью множества array = [1, 2, 3, 4, 5, 4, 3] uniq = list(set(array)) Альтернативная запись с помощью литералов вместо функций uniq = [*{*array}] #tricks
Hashtags
Објавено 8 мар.
Всё начиналось с библиотеки six, что означает цифру 6 и является результатом умножения 2*3 (напомню что six это библиотека для написания кода одновременно совместимого для Python 2 и 3). Но как обычно всегда найдется тот, кому не всё понравится и он напишет свой вариант) В итоге получаем небольшой ряд "числовых" библиотек примерно для одного и того же https://pypi.org/project/six/ https://pypi.org/project/eight/ https://pypi.org/project/nine/ Выглядит забавно. Я решил проверить, есть ли другие библиотеки с числом в названии, хотя бы до 20. И вот что нашлось: https://pypi.org/project/one/ https://pypi.org/project/two/ https://pypi.org/project/three/ four - свободно https://pypi.org/project/five/ https://pypi.org/project/six/ https://pypi.org/project/seven/ https://pypi.org/project/eight/ https://pypi.org/project/nine/ ten - свободно https://pypi.org/project/eleven/ https://pypi.org/project/twelve/ thirteen - свободно fourteen - свободно fifteen - свободно https://pypi.org/project/sixteen/ seventeen - свободно nineteen - свободно twenty - свободно Назначения у этих проектов, конечно, разные. Есть и заброшенные и популярные. Но места еще есть 😊 Занимаем пока свободно! PS. Всех уделал Em Fresh со своей линейкой Python-альбомов😁 (жмакнуть show more) PPS. Всех читательниц моего канала поздравляю с праздником 🌼🥳💐 #offtop#libs#2to3
Објавено 6 мар.
Лично я на практике встречал использование побитовых операторов в двух ситуациях (их конечно намного больше). 🔸1. Сдвиг, который соответствует некоторой математической операции (арифметический сдвиг) но работает несравнимо быстрей. Например сдвиг влево равен выражению a*2**b: a<<b == a*2**b А также определение знака числа или нахождение модуля без условного оператора, что также очень быстро делается. И другие операции. 🔸2. Числовые маски. Что это такое? Создаем несколько переменных, в которых в бинарном представлении все ячейки заполнены нулями кроме одной позиции. И у каждой переменной используется своя уникальная позиция для бита 1. FLAG1 = int('001', 2) # 2 FLAG2 = int('010', 2) # 4 FLAG3 = int('100', 2) # 8 Теперь с помощью оператора OR можем объединять все биты в одну маску >>> flags = FLAG1 | FLAG2 3 # 011 А после проверить, входит ли определённый флаг в состав битов маски? >>> flags & FLAG3 0 # 000 нет совпадений >>> flags & FLAG2 2 # 010 совпал второй бит Если результат больше 0 то флаг присутствует в маске. Если результат 0 то такого флага нет. Чтобы получить тип bool можем писать так bool(flags & FLAG2) или так flags & FLAG2 > 0 и, очевидно, так if flags & FLAG1: ... Где могут пригодиться такие маски? Один пример был в предыдущем посте про флаги в Qt фреймворке. Также такой способ часто используют в организации прав доступа к ресурсам. READ = int('001', 2) # 2 WRITE = int('010', 2) # 4 DELETE = int('100', 2) # 8 USER = READ MODERATOR = READ | WRITE ADMIN = READ | WRITE | DELETE can_write = ADMIN & WRITE Не сложно представить альтернативу на простом Python READ = 1 WRITE = 2 DELETE = 3 USER = [READ] MODERATOR = [READ, WRITE] ADMIN = [READ, WRITE, DELETE] can_write = WRITE in ADMIN Оператор in работает довольно шустро, но всё равно медленней чем побитовый оператор. #tricks
Hashtags
Објавено 4 мар.
Давайте разберёмся как работают побитовые операторы. Всего есть 6 основных операторов: | OR & AND ^ XOR (исключающее OR) ~ NOT (унарная операция) >> сдвиг вправо << сдвиг влево Эти операторы работают с числами в двоичном представлении. Условно говоря, они ставят числа в двоичном виде друг над другом и по очереди обрабатывают каждый столбик с битами. Например, берём два числа, и сразу смотрим как оно выглядит в двоичном виде (Python отбрасывает ведущие нули, так что рядом допишу более удобную форму) >>> a = 3 >>> bin(a) '0b11' # 011 >>> b = 6 >>> bin(b) '0b110' # 110 🔸 Оператор OR в результат пишет 1 если в одном из элементов есть 1 >>> 3|6 7 в двоичном виде это выглядит так (запишем столбиком) 011 |110 =111 В каждом столбце был найден 1, поэтому в результате все биты равны 1 🔸 Оператор AND В результат ставит 1 только если оба бита равны 1 >>> 3&6 2 Бинарный вид 011 &110 =010 Только на 2й позиции оба бита равны 1. 🔸 Оператор XOR Пишет 1 на бит результата, для которого только один из соответствующих битов операндов равен 1. >>> 3^6 5 011 &110 =101 🔸 Оператор NOT Заменяет каждый бит на противоположный. Эта операция унарная, то есть поддерживает только один операнд. >>> ~3 -4 ~011 =100 Здесь всё понятно. Но давайте попробуем другое число: ~50 =-51 ~110010 =-110011 Вот тут не очень понятно что произошло) Это связано со способом представления отрицательных чисел в двоичном виде. Ведь мы не можем в память записать отрицательные биты. Для этого используется ведущий 0 или 1. Но это тема не поместится в пост, советую поискать информацию в интернете самостоятельно). Если кратко и из документации, то: Побитовая операция НЕ для числа x соответствует -(x+1) 🔸Сдвиг Здесь всё просто. Все биты сдвигаются на указанное количество шагов подставляя нули >>> 3 << 1 6 011 << 1 110 Кстати, преобразовать бинарное представление обратно в число можно с помощью функции int() указав разрядность системы исчисления. >>>int('11001', 2) 25 __________________ А зачем нам вся эта информация? Узнаем в следующем посте... #triсks
Hashtags
Објавено 2 мар.
В фреймворке PyQt (и PySide тоже) часто встречается настройка чего-либо с помощью так называемых флагов. widget.setWindowFlags(Qt.Window) Взаимодействие нескольких флагов делается с помощью бинарных (или побитовых) операторов. Несколько флагов можно указать с помощью оператора "|" list_item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) исключить флаг из уже имеющегося набора можно так list_item.setFlags(list_item.flags() ^ Qt.ItemIsEnabled) Добавить новый флаг к имеющимся можно так list_item.setFlags(list_item.flags() | Qt.ItemIsEnabled) А проверка наличия делается так is_enabled = item.flags() & Qt.ItemIsEnabled > 0 Почему именно так? Всё дело в том как именно работают побитовые операторы. Но об этом в следующем посте. #qt
Hashtags
Објавено 28 фев.
Те кто работал с Python2 наверняка помнят, как приходилось поправлять расширение python-файла из переменной ˍˍfileˍˍ чтобы получить именно .py а не .pyc source_path = os.path.splitext(__file__)[0] + '.py' В Python3 эта проблема ушла. Всегда возвращается путь именно к исходному файлу .py. Ну сразу бы так) #2to3
Hashtags
Објавено 26 фев.
Часто требуется красиво распечатать ряд переменных через запятую. Возможно это требуется для дебага, а может является частью CLI. Обычно решается через метод строки join() >>> args = ['val1', 'val2', 'val3'] >>> print(", ".join(args)) val1, val2, val3 Если не все аргументы это строк то нужно их еще дополнительно преобразовать в строки. >>>args = [1, 2, 3, 4] >>> print(", ".join([str(x) for x in args])) или >>> print(", ".join(map(str, args))) 1, 2, 3, 4 Но самый простой способ это обычная функция print() (Python3) >>>args = [1, 2, 3, 4] print(*args, sep=", ") 1, 2, 3, 4 К сожалению такой способ не позволит легко сохранить получившуюся строку в переменную чтобы, например, использовать в логинге. Это возможно, но избыточно. #tricks
Hashtags
Објавено 24 фев.
Как удалить из списка повторяющиеся элементы, сохранив порядок? array = ['item1', 'item2', 'item3', 'item3', 'item1', 'item3', 'item2', 'item4'] Обычно используют преобразование в множество и обратно unq = list(set(array)) Но такой способ ломает порядок элементов. Правильный алгоритм выглядит так: 🔸Способ 0 unq = [] for item in array: if item not in unq: unq.append(item) Теперь посмотрим как это записать короче 🔸 Способ 1 Создаем пустой список и в простом генераторе сначала проверяем а потом добавляем элемент если его еще нет в списке. unq = [] [unq.append(item) for item in array if item not in unq] 🔸 Способ 2 Аналогичный, но с помощью set(). _set = set() unq = [x for x in array if x not in _set and not _set.add(x)] Здесь вторая проверка это хитрый "костыль". Функция на самом деле ничего не возвращает, просто нам надо её вызвать сразу после первой проверки, если она вернула True. Ответ функции add() инвертируем с помощью not чтобы оба условия сработали. 🔸 Способ 3 В одну строку как обычно с помощью set, но с последующей сортировкой для восстановления порядка. unq = sorted(list(set(array)), key=array.index) 🔸Способ 4 Здесь используем тот факт, что в словаре два одинаковых ключа быть не может и что ключи словаря теперь упорядочены (Python3+). Преобразуем элементы в ключи словаря и обратно в список. unq = list(dict.fromkeys(array)) ____________________ Способы 2-4 НЕ подходят, если элементы списка нехешируемые. То есть они не могут быть в качестве ключа словаря или элемента множества. Например, если у вас список словарей. В этом случае подходит только Способ 1. #tricks
Hashtags
Објавено 22 фев.
Перед вами простой словарик: data = {1: 'value1', True: 'value2'} С первого взгляда всё нормально. Давайте смотреть что у нас теперь есть в словаре >>> data[1] value2 >>> data[True] value2 Кажется мы сломали питон) Но на самом деле нет. Это ошибка разработчика а не Python. Дело в том, что на уровне данных для Python нет разницы между 1 и True. Сам тип bool это производный клас от int >>> issubclass(bool, int) True Значение True это частный случай int, равный 1. Поэтому у них одинаковый хеш, и словарь их воспринимает как один и тот же ключ >>> hash(1) 1 >>> hash(True) 1 Так что же у нас сейчас в словаре? >>> data {1: 'value2'} Ключи добавляются в порядке их следования. И если такой ключ уже существует, то вместо создания нового ключа просто обновляется его значение. Поэтому у нас всего один ключ и это 1 а не True. Чтобы избежать такой путаницы, возмите себе за правило ключи всегда делать одного типа. C "0" и False всё аналогично. #tricks
Hashtags
Објавено 20 фев.
Визуальный пример к посту про type hint
Објавено 18 фев.
Работаете в PyCharm? Тогда этот пост для вас! В Python3 добавлен синтаксис аннотаций. То есть, в объявлении функции можно указать какие типы данных у нас тут крутятся. От простых, до сложносоставных. Например, есть такая функция: def my_func(x: int, y: float) -> float: val = x * y return val В этой функции явно указаны типы, а значит, что IDE сможет адекватно анализировать ваш код и использовать всевозможные вспомогательные штуки. Автокомплит, или различные предупреждения о неверном использовании типа. Между тем, в Python2 также можно делать аннотации так, чтобы PyCharm их понял. Записываются они иначе, с помощью комментариев (type hint). Вот та же функция для Python2: def my_func(x, y): # type: (int, float) -> float val = x * y return val Интерпретатору не мешает, а для IDE подсказки😊 Но знаете ли вы, что такой способ можно использовать и не только для аннотирования функции? Можно указать тип любой переменной в любой строке! Например, у вас есть внешний API в котором типы не объявлены вообще никак. А хочется иметь автокомплиты для возвращаемых значений. Вот пример: import some_api def my_func() -> str: value = some_api.get_value() # ... life without autocomplete is pain((( return value Для переменной value IDE не сможет сообразить автокомплиты или проверку типов. Но с помощью такого же type hint мы можем ему помочь! Даже подсветка будет работать) ... value = some_api.get_value() # type: str # autocomplete for str here!!! ... После этого у переменной value появится автокомплит и всё остальное. Теперь вы можете обозначать типы переменных хоть на каждой строке 😎 Запоминаем формат: [code] # type: [Type] #tricks
Hashtags