Counter из модуля collections - вид словаря, который позволяет считать количество неизменяемых объектов (в большинстве случаев, строк). Например, можно проверить, составлены ли разные слова из одного и того же набора букв.
from collections import Counter
def check(str1, str2):
return Counter(str1) == Counter(str2)
print(check('abc', 'cba'))
# True
print(check('sdf', 'asd'))
# False
Начинаем новую серию уроков, где будем создавать приложения с пользовательским интерфейсом с помощью модуля Tkinter
Tkinter: часть 1
Tkinter: часть 1
Teletype
Tkinter: часть 1
Создаем свои первые приложения с пользовательским интерфейсом.
В отличие от некоторых языков программирования типы данных Python преобразуются в False, если они пусты, и в True, если нет. Это означает, что вам не нужно проверять, например, что длина строки, кортежа, списка или словаря равна 0. Достаточно просто проверить "правдивость" объекта.
Как и следовало ожидать, нулевое число ложно, в то время как все остальные числа истинны.
Например, следующие выражения эквивалентны. Здесь my_object - это строка, но это может быть другой тип Python (с соответствующими изменениями в тесте на равенство)
Как и следовало ожидать, нулевое число ложно, в то время как все остальные числа истинны.
Например, следующие выражения эквивалентны. Здесь my_object - это строка, но это может быть другой тип Python (с соответствующими изменениями в тесте на равенство)
my_object = 'Test' # True example
# my_object = '' # False example
if len(my_object) > 0:
print('my_object is not empty')
if len(my_object):
print('my_object is not empty')
# 0 will evaluate to False
if my_object != '':
print('my_object is not empty')
if my_object:
print('my_object is not empty')
# an empty string will evaluate to False
Enumerate - встроенная функция Python. Ее полезность не может быть сведена в одну строку. Тем не менее, большинство новичков и даже некоторые опытные программисты не знают об этом. Это позволяет нам итерировать что-либо в цикле и иметь автоматический счетчик. Вот пример:
И это еще не все, enumerate также принимает необязательный аргумент, который делает функцию еще более полезной.
Необязательный аргумент позволяет нам указать перечислить, откуда начинать индекс. Вы также можете создавать кортежи, содержащие индекс и элемент списка, используя список. Вот пример:
for counter, value in enumerate(some_list):
print(counter, value)И это еще не все, enumerate также принимает необязательный аргумент, который делает функцию еще более полезной.
my_list = ['apple', 'banana', 'grapes', 'pear']
for c, value in enumerate(my_list, 1):
print(c, value)
# Output:
# 1 apple
# 2 banana
# 3 grapes
# 4 pearНеобязательный аргумент позволяет нам указать перечислить, откуда начинать индекс. Вы также можете создавать кортежи, содержащие индекс и элемент списка, используя список. Вот пример:
my_list = ['apple', 'banana', 'grapes', 'pear']
counter_list = list(enumerate(my_list, 1))
print(counter_list)
# Output: [(1, 'apple'), (2, 'banana'), (3, 'grapes'), (4, 'pear')]Продолжаем осваивать модуль Tkinter, в этот раз учимся использовать Canvas и сразу же применяем его на практике
Tkinter: часть 2
Tkinter: часть 2
Teletype
Tkinter: часть 2
Продолжим изучение модуля Tkinter, сделав приложение, которые покажет график синусоиды.
Константы модуля string
Так как это встроенный модуль, то мы должны импортировать его перед использованием любых его констант и классов. А теперь давайте посмотрим на те самые константы, определенные в этом модуле.
Так как это встроенный модуль, то мы должны импортировать его перед использованием любых его констант и классов. А теперь давайте посмотрим на те самые константы, определенные в этом модуле.
>>> import string
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
>>> string.hexdigits
'0123456789abcdefABCDEF'
>>> string.whitespace
' \t\n\r\x0b\x0c'
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_{|}~'Контекстные менеджеры
Контекстные менеджеры — это специальные конструкции, которые представляют из себя блоки кода, заключенные в инструкцию
Простейшей функцией, использующей данный протокол является функция
Чтобы каждый раз не вызывать метод
Здесь нам не нужно каждый раз вызывать метод
Контекстные менеджеры — это специальные конструкции, которые представляют из себя блоки кода, заключенные в инструкцию
with. Инструкция with создает блок, используя протокол, контекстного менеджера. Простейшей функцией, использующей данный протокол является функция
open(). Каждый раз, когда мы открываем файл, нам необходимо его закрыть, чтобы вытолкнуть выходные данные на диск (на самом деле Python вызывает метод close() автоматически, но явное его использование является хорошим тоном). Например:file = open("file.txt", "w")
file.write("Hello, World")
file.close()Чтобы каждый раз не вызывать метод
close() мы можем воспользоваться контекстным менеджером функции open(), который автоматически закроет файл после выхода из блока:with open("file.txt", "w") as file:
file.write("Hello, World")Здесь нам не нужно каждый раз вызывать метод
close, чтобы вытолкнуть данные в файл. Из этого следует, что контекстный менеджер используется для выполнения каких-либо действий до входа в блок и после выхода из него. Но функциональность контекстных менеджеров на этом не заканчивается.Реализация класса контекстного менеджера
Начнем с того, что в контекстном менеджере должны быть определены методы
Просто определив методы
Наш метод
# test
Начнем с того, что в контекстном менеджере должны быть определены методы
__enter__ и __exit__. Давайте создадим наш собственный менеджер контекста для открытия файлов и поймем суть его работы.class NewOpen(object): def __init__(self, file_name, mode): self.file = open(file_name, mode) def __enter__(self): return self.file def __exit__(self, type, value, traceback): self.file.close()Просто определив методы
__enter__ и __exit__, мы можем использовать наш новый класс с оператором with. Давайте попробуем:with NewOpen('test.txt', 'w') as file: file.write('Hello, world!')Наш метод
__exit__ принимает три аргумента. Они требуются для каждого метода __exit__, который является частью класса.# test
В прошлых уроках мы научились рисовать графики и добавлять кнопки, в этом уроке мы с вами научимся располагать виджеты по нашему усмотрению
Tkinter: часть 3
Tkinter: часть 3
Teletype
Tkinter: часть 3
В этом уроке мы с вами научимся располагать виджеты по нашему усмотрению.
Кэширование функций
Кэширование может сэкономить время, когда связанная с вводом или выводом функция периодически вызывается с одинаковыми аргументами. До Python 3.2 мы должны были написать собственную реализацию. В Python 3.2+ есть декоратор
Давайте реализуем калькулятор чисел Фибоначчи с использованием кэша.
Советую попробовать запустить любую рекурсивную функцию с кэшированием и без него, прирост в скорости замечается сразу.
Кэширование может сэкономить время, когда связанная с вводом или выводом функция периодически вызывается с одинаковыми аргументами. До Python 3.2 мы должны были написать собственную реализацию. В Python 3.2+ есть декоратор
lru_cache, который позволяет нам быстро кэшировать и вскрывать возвращаемые значения функции.Давайте реализуем калькулятор чисел Фибоначчи с использованием кэша.
from functools import lru_cache@lru_cache(maxsize=32)def fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2)>>> print([fib(n) for n in range(10)])# Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]Советую попробовать запустить любую рекурсивную функцию с кэшированием и без него, прирост в скорости замечается сразу.
Forwarded from Hello World
“is” vs “==“
Два списка указывают на один и тот же объект:
Результат:
Пробуем создать абсолютно новый объект:
Результат:
📎 is возвратит True, если обе переменные ссылаются на один объект
📎 == возвратит True, если сравниваемые объекты идентичны
#tips
Два списка указывают на один и тот же объект:
>>> a = [1, 2, 3]
>>> b = a
Результат:
>>> a is b
True
>>> a == b
True
Пробуем создать абсолютно новый объект:
>>> c = a[:]
Результат:
>>> a == c
True
>>> a is c
False
📎 is возвратит True, если обе переменные ссылаются на один объект
📎 == возвратит True, если сравниваемые объекты идентичны
#tips
Учимся работать с полями для пользовательского ввода и вывода данных, а также практикуемся в использовании кнопок
Tkinter: часть 4
Tkinter: часть 4
Teletype
Tkinter: часть 4
В этом уроке я решил разобрать тему работы с такими новыми штуками, как Label, Entry и Focus.
Использование списков в качестве стеков
Стек — абстрактный тип данных, представляющий собой список элементов, организованных по принципу LIFO (англ. last in — first out, «последним пришёл — первым вышел»).
Методы встроенного списка в Python позволяют очень легко использовать список в виде стека. Чтобы добавить элемент на вершину стека, используйте
Стек — абстрактный тип данных, представляющий собой список элементов, организованных по принципу LIFO (англ. last in — first out, «последним пришёл — первым вышел»).
Методы встроенного списка в Python позволяют очень легко использовать список в виде стека. Чтобы добавить элемент на вершину стека, используйте
append(). Чтобы извлечь элемент из верхней части стека, используйте pop() без явного индекса. Пример:>>> stack = [3, 4, 5]>>> stack.append(6)>>> stack[3, 4, 5, 6]>>> stack.pop()6>>> stack[3, 4, 5]>>> stack.pop()5Выражение del
Существует способ удалить элемент из списка по его индексу, а не по значению - с помощью оператора del. Это отличается от метода pop(), который возвращает значение. Оператор del также можно использовать для удаления фрагментов из списка или очистки всего списка. Например:
del также может быть использован для удаления целых переменных:
Обращение к этой переменной в дальнейшем вызовет ошибку (по крайней мере, пока ей не присвоено другое значение).
Существует способ удалить элемент из списка по его индексу, а не по значению - с помощью оператора del. Это отличается от метода pop(), который возвращает значение. Оператор del также можно использовать для удаления фрагментов из списка или очистки всего списка. Например:
>>> a = [1, 2, 3, 4, 5, 6]>>> del a[0]>>> a[2, 3, 4, 5, 6]>>> del a[2:4]>>> a[2, 3, 6]>>> del a[:]>>> a[]del также может быть использован для удаления целых переменных:
>>> del aОбращение к этой переменной в дальнейшем вызовет ошибку (по крайней мере, пока ей не присвоено другое значение).
"Быстрый" контейнер deque
Deque может быть реализован на Python с помощью модуля collections. Deque предпочтительнее, чем обычный список, в тех случаях, когда нам нужны более быстрые операции добавления и вытягивания элементо из обоих концов контейнера, поскольку deque обеспечивает линейную сложность O(1) для операций добавления и выталкивания по сравнению со списком, у которого сложность по времени для тех операций составляет O(n). Вот пример основных методов:
Также для deque есть возможность использовать стандартные функции по типу sum, min, max и тому подобные.
Deque может быть реализован на Python с помощью модуля collections. Deque предпочтительнее, чем обычный список, в тех случаях, когда нам нужны более быстрые операции добавления и вытягивания элементо из обоих концов контейнера, поскольку deque обеспечивает линейную сложность O(1) для операций добавления и выталкивания по сравнению со списком, у которого сложность по времени для тех операций составляет O(n). Вот пример основных методов:
>>> from collections import deque>>> x = deque([1, 2, 3])>>> x.append(4)>>> x.appendleft(0)>>> xdeque([0, 1, 2, 3, 4])>>> x.pop()4>>> x.popleft()0>>> xdeque([1, 2, 3])Также для deque есть возможность использовать стандартные функции по типу sum, min, max и тому подобные.
Создаем свой простенький локер - вирус, блокирующий компьютер; а также используем новый интересный модуль
Tkinter: часть 5
Tkinter: часть 5
Teletype
Tkinter: часть 5
Создаем свой простенький локер - вирус, блокирующий компьютер.
Сохраняем данные с помощью pickle
Модуль pickle реализует двоичное сохранение объектных структур в Python. Однако будьте осторожнее, pickle не защищен от ошибочных или вредоносных данных. Никогда не извлекайте данные, полученные из ненадежных или не прошедших проверку подлинности источников.
Для начала поробуем сохранить, к примеру, список из различных типов данных.
Данные успешно сохранены, теперь откроем и убедимся в их сохранности.
Что сохранили, то и получили - всё верно. В итоге, pickle - хорошее решение, на случай, когда требуется сохранить что-либо, а на написание полноценной базы данных нет времени.
Модуль pickle реализует двоичное сохранение объектных структур в Python. Однако будьте осторожнее, pickle не защищен от ошибочных или вредоносных данных. Никогда не извлекайте данные, полученные из ненадежных или не прошедших проверку подлинности источников.
Для начала поробуем сохранить, к примеру, список из различных типов данных.
import picklex = ['abc', 67, 3.14]with open('data', 'wb') as file: pickle.dump(x, file)Данные успешно сохранены, теперь откроем и убедимся в их сохранности.
with open('data', 'rb') as file: x = pickle.load(file)print(x)# Out: ['abc', 67, 3.14]Что сохранили, то и получили - всё верно. В итоге, pickle - хорошее решение, на случай, когда требуется сохранить что-либо, а на написание полноценной базы данных нет времени.
Switch-конструкция с помощью словаря
К сожалению, в Python не существует switch-конструкций, в отличие от большинства других языков программирования, и поэтому приходится строить башни из условных операторов в своём коде.
Однако есть одно хитрое решение — использовать словарь, где значениями будут функции. Например, напишем словарь, который будет использован для математических операторов.
В этом примере были использованы lambda-функции для простоты, но вместо них можете подставить любые другие. Для тех, кто не знает: lambda - объявление анонимной функции (можно косвенно сравнить с def); x, y - принимаемые аргументы; x + y - то, что функция возвращает.
Примерно вот так мы можем пользоваться подобной штукой. Думаю, что многие найдут полезное применение подобному использованию словарей.
К сожалению, в Python не существует switch-конструкций, в отличие от большинства других языков программирования, и поэтому приходится строить башни из условных операторов в своём коде.
Однако есть одно хитрое решение — использовать словарь, где значениями будут функции. Например, напишем словарь, который будет использован для математических операторов.
switch = { '+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x / y}В этом примере были использованы lambda-функции для простоты, но вместо них можете подставить любые другие. Для тех, кто не знает: lambda - объявление анонимной функции (можно косвенно сравнить с def); x, y - принимаемые аргументы; x + y - то, что функция возвращает.
result = switch['*'](4, 5)print(result)# Output: 20Примерно вот так мы можем пользоваться подобной штукой. Думаю, что многие найдут полезное применение подобному использованию словарей.
Как одной математической формулой по номеру месяца посчитать количество дней в нем?
Попробуем написать функцию f(x), которая бы давала следующий список значений (таблица №1), то есть количество дней в месяцах. Помимо стандартных арифметических операций, мы будем использовать целочисленное деление и взятие остатка по модулю.
Обычно количество дней в месяце колеблется между 30 и 31. При этом, можно заметить зависимость этого числа от четности месяца — значит, воспользуемся операцией взятия остатка по модулю 2. Кажется, это должно быть нечто, вроде:
Пока что не обращая внимания на февраль, нам нужно, чтобы +1 в делимом «активировалось» только при достижении аргументом значений, больших 8. При этом значения аргумента не могут превосходить 12. Значит, нам идеально подойдет целочисленное деление аргумента на 8:
Все правильно, кроме февраля. Как неожиданно. В самой последней версии нашей формулы февралю достались целых 30 дней. А потому нам нужно отсечь у него пару дней. Естественно, от этого пострадают и еще какие-то месяцы, поэтому нам придется пожертвовать именно январем, затем подправив формулу и для него. Отсечь дни для первого и второго месяцев можно с помощью выражения 2 % x. Тогда наша формула принимает уже следующий вид:
Остался последний шаг — подлатать январь. Это сделать не так сложно: просто добавим 2 дня только к нему, т.е. к такому месяцу, чей номер меньше либо равен единице. Как вам идея использовать для этой цели
Превосходно, 12 из 12. Подобная функция на языке Python может быть записана следующим образом:
Попробуем написать функцию f(x), которая бы давала следующий список значений (таблица №1), то есть количество дней в месяцах. Помимо стандартных арифметических операций, мы будем использовать целочисленное деление и взятие остатка по модулю.
Обычно количество дней в месяце колеблется между 30 и 31. При этом, можно заметить зависимость этого числа от четности месяца — значит, воспользуемся операцией взятия остатка по модулю 2. Кажется, это должно быть нечто, вроде:
f₁(x) = 30 + x % 2# таблица №2Пока что не обращая внимания на февраль, нам нужно, чтобы +1 в делимом «активировалось» только при достижении аргументом значений, больших 8. При этом значения аргумента не могут превосходить 12. Значит, нам идеально подойдет целочисленное деление аргумента на 8:
f₃(x) = 30 + (x + x // 8) % 2# таблица №3Все правильно, кроме февраля. Как неожиданно. В самой последней версии нашей формулы февралю достались целых 30 дней. А потому нам нужно отсечь у него пару дней. Естественно, от этого пострадают и еще какие-то месяцы, поэтому нам придется пожертвовать именно январем, затем подправив формулу и для него. Отсечь дни для первого и второго месяцев можно с помощью выражения 2 % x. Тогда наша формула принимает уже следующий вид:
f₄(x) = 28 + (x + x // 8) % 2 + 2 % x# таблица №4Остался последний шаг — подлатать январь. Это сделать не так сложно: просто добавим 2 дня только к нему, т.е. к такому месяцу, чей номер меньше либо равен единице. Как вам идея использовать для этой цели
1 // x? Проверяем:f₅(x) = 28 + (x + x // 8) % 2 + 2 % x + 1 // x * 2# таблица №5Превосходно, 12 из 12. Подобная функция на языке Python может быть записана следующим образом:
f = lambda x: 28 + (x + x // 8) % 2 + 2 % x + 1 // x * 2print(f'В июне {f(6)} дней')# Out: В июне 30 днейurlencode
Довольно часто приходится работать с разнообразными API и совершать get-запросы с передачей множества параметров. Чаще всего составление запроса в коде выглядит примерно так:
Смотрится не слишком презентабельно, однако есть слегка длиннее, но значительно улучающий читаемость вариант – функция urlencode из из модуля urllib:
P. S. Приносим извинения за настолько долгое отсутствие постов, возобновляем работу над каналом.
Довольно часто приходится работать с разнообразными API и совершать get-запросы с передачей множества параметров. Чаще всего составление запроса в коде выглядит примерно так:
url = 'https://example.com?item={}&size={}&color={}&amount={}'.format('t-shirt', 'M', 'white', 5)Смотрится не слишком презентабельно, однако есть слегка длиннее, но значительно улучающий читаемость вариант – функция urlencode из из модуля urllib:
from urllib.parse import urlencodeurl = 'https://example.com'params = { 'item': 't-shirt', 'size': 'M', 'color': 'white', 'amount': 5}encoded_params = urlencode(params)url += '?' + encoded_paramsprint(url)# Output: example.com?item=t-shirt&size=M&color=white&amount=5P. S. Приносим извинения за настолько долгое отсутствие постов, возобновляем работу над каналом.
Абстрактные методы в Python
В абстрактном классе обычно реализуется общая часть нескольких сущностей или другими словами - абстрактная сущность.
Абстрактный метод – это метод, который не имеет своей реализации в базовом классе, и он должен быть реализован в классе-наследнике.
Для того, чтобы создать абстрактный класс с абстрактными методами, надо импортировать вспомогательные метакласс ABCMeta и декоратор abstractmethod из модуля abc.
Если мы отнаследуем новый класс от абстрактного класса, не переопределив абстрактные методы (в данном случае function), и попробуем создать экземпляр, то получим исключение:
Для того, чтобы код заработал корректно, нам необходимо переопределить все абстрактные методы. То есть по сути еще раз просто написать функцию, но уже в новом классе.
В абстрактном классе обычно реализуется общая часть нескольких сущностей или другими словами - абстрактная сущность.
Абстрактный метод – это метод, который не имеет своей реализации в базовом классе, и он должен быть реализован в классе-наследнике.
Для того, чтобы создать абстрактный класс с абстрактными методами, надо импортировать вспомогательные метакласс ABCMeta и декоратор abstractmethod из модуля abc.
from abc import ABCMeta, abstractmethodclass AbstractClass(metaclass=ABCMeta): @abstractmethod def function(self): passЕсли мы отнаследуем новый класс от абстрактного класса, не переопределив абстрактные методы (в данном случае function), и попробуем создать экземпляр, то получим исключение:
class BadExample(AbstractClass): passchild = BadExample() # TypeError: Can't instantiate abstract class BadExample with abstract methods functionДля того, чтобы код заработал корректно, нам необходимо переопределить все абстрактные методы. То есть по сути еще раз просто написать функцию, но уже в новом классе.
class GoodExample(AbstractClass): def function(self): print('Everything is ok')anotherchild = GoodExample()