Python декораторы.
Как-то долго я ходил вокруг да около, а про любимый Python забыл. Сегодня попытаюсь объяснить вам что такое декораторы.
Декоратор - наверное, самый популярный паттерн, суть которого заключается в том, чтобы максимально быстро и просто расширить функционал исходной функции. Также стоит запомнить такое правило: декоратор - функция, которая в качестве аргумента принимает функцию и возвращает функцию. Давайте сразу к примеру:ᅠ
1. Определим функцию say_hello(name), которая на вход получит имя человека:
#python #github
Как-то долго я ходил вокруг да около, а про любимый Python забыл. Сегодня попытаюсь объяснить вам что такое декораторы.
Декоратор - наверное, самый популярный паттерн, суть которого заключается в том, чтобы максимально быстро и просто расширить функционал исходной функции. Также стоит запомнить такое правило: декоратор - функция, которая в качестве аргумента принимает функцию и возвращает функцию. Давайте сразу к примеру:ᅠ
1. Определим функцию say_hello(name), которая на вход получит имя человека:
python2. Отлично. А теперь определим декоратор, который скажет что-то приятное после приветствия:
def say_hello(name):
print('Hello,', name)
say_hello('Денис')
>>> Hello, Денис
def you_are_beautiful(func): # На вход поступает функцияЕсть один нюанс, который нужно соблюсти - декоратор должен быть объявлен ДО декорируемой функции. А способов применить декоратор несколько, но для Python самый актуальный способ, так называемый «Синтаксический сахар», на примере:
def wrapped(*args, **kwargs): # обрабатываем аргументы
func(*args, **kwargs) # вызывает функцию извне
print('Классно выглядишь сегодня ;)')
return wrapped # возвращает функцию, но не вызывает!!!
# (возвращает ссылку на функцию, без скобок)
# сначала определяем декораторПод коробкой вызов функции выглядит так:
def you_are_beautiful(func):
def wrapped(*args, **kwargs):
func(*args, **kwargs)
print('Классно выглядишь сегодня ;)')
return wrapped
# далее определяем функцию и навешиваем декоратор
@you_are_beautiful <-- наш декоратор
def say_hello(name):
print('Hello,', name)
say_hello('Денис')
>>> Hello, Денис
>>> Классно выглядишь сегодня ;)
you_are_beautiful(say_hello('Денис'))Ну и, соответственно, декораторов может быть навешано несколько:
@decorator1По итогу получаем задекорированную функцию. Что-то выполнилось до вызова функции, что-то после, и это очень удобно в некоторых задачах. Обещаю сделать отдельный репозиторий/папку для своих декораторов, прикреплю ссылку сюда позже, а отдельным постом оповещу. И спасибо за прочтение, это важно дня меня 🙃
@decorator2
@decorator3
@decorator4
def foo():
pass
# что при вызове, по сути, эквивалентно этому:
decorator1(decorator2(decorator3(decorator4(foo()))))
#python #github
Сегодня будет достаточно глубокий экскурс в Python исключения.ᅠ
Для кого-то эта тема может быть очевидной, но для некоторых начинающих разработчиков эта тема всё ещё не открыта. Итак, что же такое исключения?
Действия программы, которые противоречат тем или иным правилам вызывают исключения. Например попытка поделить на ноль вызовет
"Отловить" ошибки можно при помощи конструкции
Как же создать своё исключение? Легко:
1. Большое количество исключений - всегда сложно, запутывает и разработчиков, и пользователей.
2. Лучше предусмотреть альтернативный выход из исключительной ситуации.
3. Плохо влияет на будущую поддерживаемость и ясность вашего кода.
4. Все исключения всё равно не получится поймать.
Я уже рассказывал вам про декораторы тут, так что вот какое решение могу предложить. Оформим собственное исключение, декоратор, что сохранит любую нашу функцию и задекорируем объявленную ранее функцию
Ну и естественно моё решение далеко не эталонно, но оно уже в разы лучше и удобнее, чем писать в каждой функции свой собственный обработчик (за редким исключением). Если вам нужно быстро обезопасить свою функцию, то это вполне себе неплохое решение.
Способов решить проблему исключений есть ещё много, а весь материал, что я изложил тут, чрезвычайно сжат. Новичкам я конечно же советую погрузиться в тему глубже. Это важнее, чем кажется.
А этот декоратор был бы неплохим началом для моей коллекции декораторов, да?)
#python
Для кого-то эта тема может быть очевидной, но для некоторых начинающих разработчиков эта тема всё ещё не открыта. Итак, что же такое исключения?
Действия программы, которые противоречат тем или иным правилам вызывают исключения. Например попытка поделить на ноль вызовет
ZeroDivisionError
, а попытка сложить строку и кортеж - TypeError
."Отловить" ошибки можно при помощи конструкции
try/except/else/finally
. Например:def division(a,b):Теперь работа программы не будет ломаться при делении на ноль, а продолжит свою работу. Но это далеко не значит, что использование блока
try:
return a/b
except ZeroDivisionError:
return None
try/except
- панацея. Об этом чуть позже. Как же создать своё исключение? Легко:
class MyOwnException(Exception):Как вы видите, для создания своего исключения мы создаём новый класс, который наследуем от базового класса
pass
или
class MyOwnException(Exception):
# разный функционал, что выполнится при исключении
Exception
. Чтобы выбросить это исключение в программе мы воспользуемся оператором raise
:# какое-то условие, что вызывает исключениеЗамечательно, удобно для программиста, быстро но теперь поговорим о том почему это плохо:
raise MyOwnException('Message')
>>> __main__.MyOwnException: Message
1. Большое количество исключений - всегда сложно, запутывает и разработчиков, и пользователей.
2. Лучше предусмотреть альтернативный выход из исключительной ситуации.
3. Плохо влияет на будущую поддерживаемость и ясность вашего кода.
4. Все исключения всё равно не получится поймать.
Я уже рассказывал вам про декораторы тут, так что вот какое решение могу предложить. Оформим собственное исключение, декоратор, что сохранит любую нашу функцию и задекорируем объявленную ранее функцию
division
. Вашему вниманию предлагаю такой код:from functools import wrapsИтак, что тут происходит? Для начала о
class Error(Exception):
def __repr__(self):
return 'Error'
def __str__(self):
return 'Error'
def safe(func):
@wraps(func)
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
return Error()
return wrapped
@safe # декорируем функцию
def division(a, b):
return a / b
division(4,0)
>>> Error
@wraps
. Я еще не рассказывал о нём, но этот декоратор нужен для сохранения таких параметров функции как __name__
и __doc__
, так как после декорирования эти параметры переписываются. Под коробкой этот декоратор на примере можно заменить вот так вот так:def safe(func)А теперь обо всём в целом. Мы создали декоратор
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
return Error()
wrapped.__name__ = func.__name__
wrapped.__doc__ = func.__doc__
return wrapped
safe
, который позволит обезопасить любую функцию от любой ошибки. При объявлении небезопасной функции с этим декоратором мы получаем абсолютно неломаемую программу, а выглядит решение ну очень уж лаконично. Кстати, в блоке except мы можем возвращать не только наш экземпляр класса Error
, но и любое другое значение, которое нам будет удобно, например float('inf')
, что вернёт нам бесконечность. (Кстати, в рассмотренном примере не обязательно возвращать именно экземпляр класса. С таким же успехом можно вернуть просто строку "Error"
, но я оставил класс для того, чтобы вы могли легко модифицировать поведение своей ошибки)Ну и естественно моё решение далеко не эталонно, но оно уже в разы лучше и удобнее, чем писать в каждой функции свой собственный обработчик (за редким исключением). Если вам нужно быстро обезопасить свою функцию, то это вполне себе неплохое решение.
Способов решить проблему исключений есть ещё много, а весь материал, что я изложил тут, чрезвычайно сжат. Новичкам я конечно же советую погрузиться в тему глубже. Это важнее, чем кажется.
А этот декоратор был бы неплохим началом для моей коллекции декораторов, да?)
#python
Аннотации в Python.
Типизация переменных в языках - это вечная тема для обсуждения. Кому-то нравится, статическая типизация, как в Dart, например, когда мы явно объявляем новые переменные и указываем какие типы данных они могут в себе содержать, в то время, как другим нравится динамическая типизация, как в Python, где в любой момент времени можно создать и использовать новую переменную любого типа. Сейчас не будем обсуждать что лучше, а что хуже, а поговорим о том как указать тип переменной в Python явно.
Указание типа переменной происходит по определенному синтаксису, который лучше показать, чем объяснить:
Вот такая замечательная функция у нас появилось. Мы явно указываем, что
Как вы можете заметить, функция прекрасно отработала и не выдала никакой ошибки. Но как сделать так, чтобы при неправильных типах переменных функция не выполнялась? Обычно для этого предлагают использовать функцию
Теперь наша программа прервётся, если мы подадим в функцию неправильные входные параметры. Ну и, опять же, тема очень обширная, советую ознакомиться подробнее. Спасибо, что читаете ❤️
#python
Типизация переменных в языках - это вечная тема для обсуждения. Кому-то нравится, статическая типизация, как в Dart, например, когда мы явно объявляем новые переменные и указываем какие типы данных они могут в себе содержать, в то время, как другим нравится динамическая типизация, как в Python, где в любой момент времени можно создать и использовать новую переменную любого типа. Сейчас не будем обсуждать что лучше, а что хуже, а поговорим о том как указать тип переменной в Python явно.
Указание типа переменной происходит по определенному синтаксису, который лучше показать, чем объяснить:
def say_hello(name: str, age: int) -> None:
print(f"Hello, {name}. I know, you're {age} years old.")
Вот такая замечательная функция у нас появилось. Мы явно указываем, что
name
- это строка, age
- целое число, а сама функция должна возвращать None
, и теперь большинство сред разработки будут указывать нам типы переменных, когда мы захотим использовать эту функцию, НО это лишь визуальное указание, никаких изменений в ход программы это не внесёт. О чём речь? Попробуем выполнить эту функцию:say_hello('Денис', 19)
>>> Hello, Денис. I know, you're 19 years old.
# всё бы хорошо, но попробуем так:
say_hello([1, 2, 3], "СТРОКА")
>>> Hello, [1, 2, 3]. I know, you're СТРОКА years old.
Как вы можете заметить, функция прекрасно отработала и не выдала никакой ошибки. Но как сделать так, чтобы при неправильных типах переменных функция не выполнялась? Обычно для этого предлагают использовать функцию
isinstance
. На примере:def say_hello(name: str, age: int) -> None:
if isinstance(name, str) and isinstance(age, int):
print(f"Hello, {name}. I know, you're {age} years old.")
else:
raise TypeError('Подан неверный тип переменной')
say_hello('Денис', 19)
>>> Hello, Денис. I know, you're 19 years old.
say_hello([1, 2, 3], "СТРОКА")
>>> TypeError: Подан неверный тип переменной
Теперь наша программа прервётся, если мы подадим в функцию неправильные входные параметры. Ну и, опять же, тема очень обширная, советую ознакомиться подробнее. Спасибо, что читаете ❤️
#python
Сегодня совсем коротко, но зато со смыслом.
Думаю, многие знают, что в Python есть такие операторы, как
Отлично, проверим?
Первые три выражения дали вполне ожидаемый ответ, а с последним всё не так однозначно.
В этом и заключается вся разница.
#python
Думаю, многие знают, что в Python есть такие операторы, как
is
и ==
. Оба они идейно похожи - они указывают на равенство объектов. Казалось бы, одно и то же, но давайте на примере:# объявим наши переменные
# таким образом
a = [1, 2, 3]
b = a
c = [1, 2, 3]
Отлично, проверим?
a == b
>>> True
a is b
>>> True
a == c
>>> True
a is c
>>> False
Первые три выражения дали вполне ожидаемый ответ, а с последним всё не так однозначно.
a == b == c == [1, 2, 3]
, с этим не поспорить. b = a
, значит b
- ссылка на объект a
, следовательно обе переменные ссылаются на один и тот же список [1, 2, 3]
в памяти. А вот c
- это уже новый объект в памяти, и пусть даже c == a
, но это разные объекты. Именно поэтому a is c ⇒ False
.В этом и заключается вся разница.
#python
Области видимости в Python.
Так, с последним моим переездом пропустил два дня для поста, но, собственно, ничего вроде страшного. Сейчас я снова в стою и буду писать, пока пишется.
Области видимости (О.В. в примере) в языках программирования рассматриваются как некоторые сущности, знаете. Этот термин подразумевает область программы, откуда будет доступна переменная, функция и т.п. структуры.
Из теории тут ничего особо важного да и сложного нет. Все принципы примерно похожи для большинства языков, но на примере Python:
Что тут происходит? Всё просто: две переменные
Таким образом переменные
Кстати, с областями видимости есть классная и очень интересная особенность - замкнутость. Она много где используется, например в тех-же декораторах. Может быть я напишу об этом позже, конечно, но советую самостоятельно ознакомиться, тема интересная. Ну и конечно же есть смысл посмотреть про ключевые слова global и nonlocal, но помните, что использование этих ключевых слов не очень хороший тон в программировании.
Спасибо прочтение и классный фидбек в личных сообщениях, это дорогого стоит
#python
Так, с последним моим переездом пропустил два дня для поста, но, собственно, ничего вроде страшного. Сейчас я снова в стою и буду писать, пока пишется.
Области видимости (О.В. в примере) в языках программирования рассматриваются как некоторые сущности, знаете. Этот термин подразумевает область программы, откуда будет доступна переменная, функция и т.п. структуры.
Из теории тут ничего особо важного да и сложного нет. Все принципы примерно похожи для большинства языков, но на примере Python:
# глобальная O.B.
a = 5
b = 6
def foo(): # foo О.В.
c = 7
return a * b
foo()
>>> 30
print(c)
>>> NameError: name 'c' is not defined
Что тут происходит? Всё просто: две переменные
a
и b
мы объявляем в глобальной области видимости, а c
в области видимости функции foo
. И тут нужно понять, что области видимости работают по принципу вложенности: переменные из родителя доступны в ребёнке, но не наоборот (!). Таким образом переменные
a
и b
доступны в функции foo
, но c
не доступна в глобальной области видимости, переменная локальна. Кстати, с областями видимости есть классная и очень интересная особенность - замкнутость. Она много где используется, например в тех-же декораторах. Может быть я напишу об этом позже, конечно, но советую самостоятельно ознакомиться, тема интересная. Ну и конечно же есть смысл посмотреть про ключевые слова global и nonlocal, но помните, что использование этих ключевых слов не очень хороший тон в программировании.
Спасибо прочтение и классный фидбек в личных сообщениях, это дорогого стоит
#python
Зачем нужны абстрактные методы и классы?
Думаю, что многие знаю о существовании абстракции в языках программирования, но даже если вы не слышали об этом, то сейчас я объясню это в максимально простом виде 🙃
Давайте начну с примера из личного опыта. Может быть затяну из-за этого, но должно быть интересно. Так вот, недавно я работал в стартапе из кремниевой долины. Мы с командой создавали чат-бота, который будет работать во всех мессенджерах, будь то Telegram, VK, What's App, Viber или Facebook Messenger.
Как тут быть? У каждого мессенджера свой API со своими входными и выходными, мы столкнулись с проблемой стандартизации. Тогда мы просто взяли и написали свой интерфейс для каждого мессенджера. Стандартом интерфейса и стал абстрактный класс с абстрактными методами. Так что же это такое?
Абстрактный класс - класс, унаследованный от класса
Абстрактный метод - метод класса, задекорированный декоратором
Давайте на примере, так будет яснее. Отдалённо повторим интерфейс мессенджера из нашего проекта:
Что происходит в этом примере? Я объявил класс Interface, который унаследован от абстрактного класса
Потом мы реализуем класс, например
Надеюсь этот пример помог вам понять что это такое и немного разобраться.
#python
Думаю, что многие знаю о существовании абстракции в языках программирования, но даже если вы не слышали об этом, то сейчас я объясню это в максимально простом виде 🙃
Давайте начну с примера из личного опыта. Может быть затяну из-за этого, но должно быть интересно. Так вот, недавно я работал в стартапе из кремниевой долины. Мы с командой создавали чат-бота, который будет работать во всех мессенджерах, будь то Telegram, VK, What's App, Viber или Facebook Messenger.
Как тут быть? У каждого мессенджера свой API со своими входными и выходными, мы столкнулись с проблемой стандартизации. Тогда мы просто взяли и написали свой интерфейс для каждого мессенджера. Стандартом интерфейса и стал абстрактный класс с абстрактными методами. Так что же это такое?
Абстрактный класс - класс, унаследованный от класса
ABC
и содержащий абстрактные методы.Абстрактный метод - метод класса, задекорированный декоратором
@abstractmethod
и не имеющей реализации. Такой метод нужен только для объявления. Давайте на примере, так будет яснее. Отдалённо повторим интерфейс мессенджера из нашего проекта:
from abc import ABC, abstractmethod
class Interface(ABC):
@abstractmethod
def send_message(self, chat_id, *args, **kwargs):
pass
@abstractmethod
def send_photo(self, chat_id, txt=None, *args, **kvargs):
pass
@abstractmethod
def send_file(self, file, txt=None, media=None):
pass
# Ну и так далее
Что происходит в этом примере? Я объявил класс Interface, который унаследован от абстрактного класса
ABC
. В этом классе я объявил 3 абстрактных метода. У них нет реализации. Суть абстрактного класса заключается лишь в том, чтобы обязать наследника класса Interface
реализовать все необходимые методы.Потом мы реализуем класс, например
Telegram
, где реализуем метод send_message
одним кодом, а в классе WhatsApp
реализуем тот же метод совсем по другому. Нас не волнует как это работает внутри, мы лишь описываем необходимый интерфейс взаимодействия.Надеюсь этот пример помог вам понять что это такое и немного разобраться.
#python
Зачем нужен json.
Казалось бы, вопрос вполне очевидный, но далеко не для всех. Сегодня расскажу про json и его особенности.
Итак, json - это формат передачи данных. Многие связывают его исключительно с JavaScript и WebDev, но в современном мире это далеко не так. Многие языки способны обрабатывать json и имеют для этого встроенные функции/модули. Например в Python есть встроенный пакет json, который позволит вам легко обработать этот формат и, например, перевести json в обычный питоновский словарь для облегчения работы.
Что же делает json таким популярным? Ну, очевидно, это удобство использования. Если вспоминать ближайшего конкурента, а именно xml, то лично мне json кажется более читабельным и удобным в работе. В своей практике я работал с обоими технологиями, и правды ради обе удобны. У каждой есть свои плюсы и минусы, но и сферы применения так же разнятся.
ᅠ
Но насчёт читабельности, предлагаю оформить одну и ту же структуру данных сначала в json, а затем в xml:
Используется же json чаще всего в случаях, когда нужно быстро получить какой-то ответ от сервера. И речь тут не только о Web. Например, в формате json ответ от сервера могут получать мобильные приложения. Ну и конечно же этот формат данных крайне популярен в REST API, о которых я писал тут.
#python #web #mobile
Казалось бы, вопрос вполне очевидный, но далеко не для всех. Сегодня расскажу про json и его особенности.
Итак, json - это формат передачи данных. Многие связывают его исключительно с JavaScript и WebDev, но в современном мире это далеко не так. Многие языки способны обрабатывать json и имеют для этого встроенные функции/модули. Например в Python есть встроенный пакет json, который позволит вам легко обработать этот формат и, например, перевести json в обычный питоновский словарь для облегчения работы.
Что же делает json таким популярным? Ну, очевидно, это удобство использования. Если вспоминать ближайшего конкурента, а именно xml, то лично мне json кажется более читабельным и удобным в работе. В своей практике я работал с обоими технологиями, и правды ради обе удобны. У каждой есть свои плюсы и минусы, но и сферы применения так же разнятся.
ᅠ
Но насчёт читабельности, предлагаю оформить одну и ту же структуру данных сначала в json, а затем в xml:
{Вот такая произвольная структура получилась для книги, которую я читаю в данный момент, кстати. Теперь повторим ее на xml:
"name": "JavaScript для чайников",
"authors": [
"Крис Минник",
"Ева Холланд"
],
"publisher": {
"name": "Диалектика",
"email": "info@dialektika.com",
"site": "www.dialektika.com"
}
}
<book>Не знаю как вам, но лично мне json кажется в разы дружелюбнее и читабельнее.
<name>JavaScript для чайников</name>
<authors>
<author>Крис Минник</author>
<author>Ева Холланд</author>
</authors>
<publisher>
<name>Диалектика</name>
<email>info@dialektika.com</email>
<site>www.dialektika.com</site>
</publisher>
</book>
Используется же json чаще всего в случаях, когда нужно быстро получить какой-то ответ от сервера. И речь тут не только о Web. Например, в формате json ответ от сервера могут получать мобильные приложения. Ну и конечно же этот формат данных крайне популярен в REST API, о которых я писал тут.
#python #web #mobile
Ещё один оператор присвоения в Python.
Думаю мало кто знает (ведь для многих людей читать спеки - грех), но в python 3.8+ появился новый оператор присвоения - Walrus operator. Я точно не знаю как перевести его на русский, но Google Translate говорит, что это "Моржовой оператор", так что не будем перечить гуру. В чём суть?
Теперь в Python есть два оператора присваивания:
#python
Думаю мало кто знает (ведь для многих людей читать спеки - грех), но в python 3.8+ появился новый оператор присвоения - Walrus operator. Я точно не знаю как перевести его на русский, но Google Translate говорит, что это "Моржовой оператор", так что не будем перечить гуру. В чём суть?
Теперь в Python есть два оператора присваивания:
# обычное присваиваниеПонятнее на примере:
# 1. Присваивает переменной x значение 5
x = 5
# walrus operator
# 1. Присваивает переменной x значение 5
# 2. Возвращает 5
(x := 5)
1. Обычное присваивание:2. Walrus operator:
with open(file) as f:
while True:
chunk = f.read(8192)
if not chunk:
break
chunk_processing(chunk)
with open(file) as f:Запись гораздо короче, как можно заметить, да и в целом повышается читабельность кода. Но лучше не увлекаться, как всегда, а то можно сделать гораздо хуже.
while chink := f.read(8192):
chunk_processing(chunk)
#python
Запускаем своего первого телеграм бота на Python.
Я уже как-то затрагивал ботов обзорно вот в этом посте, сегодня хочу продолжить немного более конкретно. Итак, телеграм сейчас является самой лучшей площадкой для создания ботов. Ни один другой мессенджер или соцсеть не может похвастаться таким же успехом в этом деле. Объяснить это просто:
1. У телеграма прекрасный, удобный, хорошо задокументированный API.
2. Для него уже сейчас существует огромная кодовая база, десятки библиотек на самых разных языках программирования.
Для примера я взял Python, так как этот язык наиболее распространен среди аудитории моего канала, как мне кажется. Для Python есть две неплохие библиотеки - это pyTelegramBotApi и aiogram. Я написал уже где-то ботов 15 за всё время программирования и с уверенностью могу сказать, что на моей практике это лучшие библиотеки.
Aiogram прекрасен своей асинхронностью, а следовательно эффективностью в высоконагруженным проекте, а pyTelegramBotApi - это синхронный младший брат, который, конечно, менее эффективен, но которого более чем достаточно в большинстве задач. pyTelegramBotApi максимально прост, так что в этой библиотеке разберётся любой.
Для начала зарегистрируем нового бота у @botfather. Это не сложно, не будем на этом останавливаться.
Потом установим библиотеку:
Первое, что нужно обсудить - это объект message, который в себя принимает функция
Второе, конечно же, декоратор
Это, конечно же, не единственный декоратор, который есть в библиотеке, но его одного достаточно для простейшего бота.
Насчёт
Это метод, который, как очевидно, отправляет сообщение пользователю. В приведенном выше примере мы отправляем сообщение по идентификатору
Теперь я напишу маленького бота, на примере которого, я надеюсь, вы поймёте тему лучше.
Посмотреть код можно тут.
Взаимодействовать с ботом: @progway_test_bot
И, как всегда, спасибо за прочтение ❤️
#python #chatbot
Я уже как-то затрагивал ботов обзорно вот в этом посте, сегодня хочу продолжить немного более конкретно. Итак, телеграм сейчас является самой лучшей площадкой для создания ботов. Ни один другой мессенджер или соцсеть не может похвастаться таким же успехом в этом деле. Объяснить это просто:
1. У телеграма прекрасный, удобный, хорошо задокументированный API.
2. Для него уже сейчас существует огромная кодовая база, десятки библиотек на самых разных языках программирования.
Для примера я взял Python, так как этот язык наиболее распространен среди аудитории моего канала, как мне кажется. Для Python есть две неплохие библиотеки - это pyTelegramBotApi и aiogram. Я написал уже где-то ботов 15 за всё время программирования и с уверенностью могу сказать, что на моей практике это лучшие библиотеки.
Aiogram прекрасен своей асинхронностью, а следовательно эффективностью в высоконагруженным проекте, а pyTelegramBotApi - это синхронный младший брат, который, конечно, менее эффективен, но которого более чем достаточно в большинстве задач. pyTelegramBotApi максимально прост, так что в этой библиотеке разберётся любой.
Для начала зарегистрируем нового бота у @botfather. Это не сложно, не будем на этом останавливаться.
Потом установим библиотеку:
pip install pyTelegramBotApi
Далее создадим файл bot.py
и напишем вот такой код:import telebotДалее разберем основы:
bot = telebot.TeleBot(токен от @BotFather)
@bot.message_handler(commands=['start'])
def send_welcome(message):
bot.send_message(message.chat.id, "привет")
bot.polling(none_stop=True)
Первое, что нужно обсудить - это объект message, который в себя принимает функция
send_message
. Message - обычный питоновский словарь, к которому мы можем обращаться по ключам. Принт этого объекта можно посмотреть тут.Второе, конечно же, декоратор
bot.message_handler(commands=['start'])
. Весь его функционал заключается в том, что функция, обёрнутая декоратором, будет выполнятся на определенную команду, например. То есть мы можем оформить декоратор bot.message_handler(commands=['help', 'помощь'])
и описанная ниже функция сработает при командах /help
и /помощь
.Это, конечно же, не единственный декоратор, который есть в библиотеке, но его одного достаточно для простейшего бота.
Насчёт
bot.send_message
. Это метод, который, как очевидно, отправляет сообщение пользователю. В приведенном выше примере мы отправляем сообщение по идентификатору
message.chat.id
, то есть в ответ пользователю. У этого класса есть еще много методов, например для отправки фотографии, аудио, игр или других действий.Теперь я напишу маленького бота, на примере которого, я надеюсь, вы поймёте тему лучше.
Посмотреть код можно тут.
Взаимодействовать с ботом: @progway_test_bot
И, как всегда, спасибо за прочтение ❤️
#python #chatbot
Как передать параметры в программу Python из консоли.
Я думаю многие видели конструкции запуска файлов типа
В общем, штука полезная и знать её точно стоило бы, но как реализовать - непонятно.
Я покажу 2 способа:
Первый через встроенную библиотеку sys. Мы получаем список всех аргументов, которые у нас есть при запуске, и уже после можем по нему итерироваться, например:
Второй вариант уже куда более изящный - там я использую библиотеку argparse:
#python
Я думаю многие видели конструкции запуска файлов типа
python file.py -n ProgWay —url t.me/prog_way_blog
Такие конструкции бывают полезны, когда скрипт запускается с определенными параметрами автоматически. Как самый близкий мне пример, когда нужно реализовать автоматизированный обработчик логов. Мы получаем на сервер новый чанк информации, засовываем её в в скрипт и на выходе получаем проанализированный файлик, например. В общем, штука полезная и знать её точно стоило бы, но как реализовать - непонятно.
Я покажу 2 способа:
Первый через встроенную библиотеку sys. Мы получаем список всех аргументов, которые у нас есть при запуске, и уже после можем по нему итерироваться, например:
import sysТогда при запуске вот такой конструкции:
for param in sys.argv:
print(param)
python file.py -n ProgWay —url t.me/prog_way_blog
Мы получим вывод:file.pyС этим уже можно работать, но при большом количестве аргументов ваш код постепенно будет превращаться в нечитабельное говно с огромным количеством условных конструкций, что не есть хорошо.
-n
ProgWay
—url
t.me/prog_way_blog
Второй вариант уже куда более изящный - там я использую библиотеку argparse:
import sysТогда при вводе той же строки:
import argparse
def getArgs():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name', default="ProgWay")
parser.add_argument('-u', '--url', default="t.me/prog_way_blog")
return parser.parse_args()
if __name__ == "__main__":
args = getArgs()
print(args.name)
python file.py -n ProgWay —url t.me/prog_way_blog
Мы получим объект, из которого по ключам можем легко достать любой аргумент.args.name // ProgWayТаким образом организовать получение аргументов из командной строки очень просто и эффективно. Спасибо за прочтение ❤️
args.url // t.me/prog_way_blog
#python
О сокращении операторов сравнения в Python.
По сути своей, операция сравнения в языках программирования - это бинарная операция, то есть сравнение возможно только для двух объектов. Если объект будет один, то не понятно с чем сравнивать, а если больше 2, то не понятно как. Но если нужно организовать проверку переменной на вхождение в какой-то в диапазон, то обычно это делают так:
ᅠ
В Python же подобные цепочки нормально распознаются и они могут быть чуть ли не бесконечными, то есть условие
Такой небольшой хак, если угодно. Казалось бы, очевидно и логично, но многие другие языки программирования такие операции не поддерживают🤔
#python
По сути своей, операция сравнения в языках программирования - это бинарная операция, то есть сравнение возможно только для двух объектов. Если объект будет один, то не понятно с чем сравнивать, а если больше 2, то не понятно как. Но если нужно организовать проверку переменной на вхождение в какой-то в диапазон, то обычно это делают так:
a = 5Но на самом деле в Python можно записать то же самое, только используя обычные правила математики:
if (a > 1) and (a < 9):
print(a)
a = 5В JavaScript, например, при такой записи условие просто не сработает и при любом значении переменной оператор выполнится.
if 1 < a < 9:
print(a)
ᅠ
В Python же подобные цепочки нормально распознаются и они могут быть чуть ли не бесконечными, то есть условие
1 < a < b < c < d < e < 9
в Python считается достаточно обыденным и распознается без проблем.Такой небольшой хак, если угодно. Казалось бы, очевидно и логично, но многие другие языки программирования такие операции не поддерживают🤔
#python
Модульность в Python.
Есть несколько видов импортов, которые вы можете использовать. Самые простые - импорты стандартных и установленных библиотек, например:
При работе над большим проектом ваша кодовая база очень быстро разрастается. Чтобы оформить качественную декомпозицию, оформить зоны ответственности и упростить проект в целом можно разбить проект на несколько компонентов (структура проекта на приложенной картинке и на github).
Чтобы импортировать файл из той же папки, в которой находится исполняемый файл, можно использовать уже знакомую конструкцию. Допустим, рядом есть файл
Содержание файла
Теперь в главном файле просто импортируем наш
Тема сложнее, чем можно рассмотреть в одном моём посте, так что заинтересовавшиеся погуглят ещё, надеюсь. Мой тестовый проект доступен на github. Хранит вас бог.
#python
Есть несколько видов импортов, которые вы можете использовать. Самые простые - импорты стандартных и установленных библиотек, например:
import FlaskС этими импортами многие знакомы, останавливаться на них не будем.
from random import randint
При работе над большим проектом ваша кодовая база очень быстро разрастается. Чтобы оформить качественную декомпозицию, оформить зоны ответственности и упростить проект в целом можно разбить проект на несколько компонентов (структура проекта на приложенной картинке и на github).
Чтобы импортировать файл из той же папки, в которой находится исполняемый файл, можно использовать уже знакомую конструкцию. Допустим, рядом есть файл
config.py
, куда вынесены все константы. Импортировать его можно так:import config
Также рядом с исполняемым файлом вы можете создать папку, куда вложите config.py
. Такой файл можно импортировать вот так:from folder import utils
Из вложенной в папку папки (какое странно выражение) импортируем так:from folder.folder2 import utils2
Также вы можете создать собственный независимый проект, чтобы переиспользовать его где-то ещё. Для этого рядом с главным файлом мы создадим папку package
с файлами __init__.py
и functions.py
. Содержание файла
__init__.py
:from package.functions import sayHelloСодержание файла
def init():
print('Инициализировано')
functions.py
:def sayHello():
print('hello')
Теперь в главном файле просто импортируем наш
package
, с такой структурой нам будут доступны все вложенные функции. Тема сложнее, чем можно рассмотреть в одном моём посте, так что заинтересовавшиеся погуглят ещё, надеюсь. Мой тестовый проект доступен на github. Хранит вас бог.
#python