Дисклеймер: я вообще не претендую на право быть умным и правильным программистом и сто процентов что-то делаю не так и пишу что-то не так и даже ничего не понимаю, прошу отнестись к данной статье только как к возможности поразмыслить. А если вы еще и подскажете как мне переосмыслить данный казус, то я буду в восторге!
Кто я?
Программист на C# работаю на шарпе 5 лет разрабатывал максимально разные проекты, от десктопных программ, до веб приложений и телеграмм ботов и вот последних я и затрону в этой статье.
Что меня смутило?
Начну с того что C# это ООП язык, и я, когда пишу на нем, использую объекты настолько, насколько мне позволяет язык. Python в этом плане тоже ООП но есть нюанс (если вспомнить пошлый анекдот =D).
Нюанс вот в чем: Внутри объекта есть переменные и функции, и чтобы внутри функции обратиться к переменным данного объекта в C# есть ключевое слово this*
Класс на C#
class Human
{
string name;
int age;
public Human(string name,int age)
{
this.name = name;
this.age = age;
}
public string Identify()
{
return "Мое имя: "+this.name+" мой возраст:"+this.age;
}
}
В пайтон же есть подобное ключевое слово self которое выполняет такую же функцию, но вот тут то и нюанс. Ты должен заранее отправить внутрь данной функции параметр self
Класс на Python
class Human:
name:str
age:int
def __init__(self,name:str,age:int):
self.name = name
self.age = age
def Identify(self):
return "Мое имя: "+self.name+" мой возраст:"+str(self.age);
Насколько я понимаю, C# на этапе написания кода, определяет тело класса и сам понимает где должен быть this, а Python в свою очередь определяет тело на уровне компиляции.
Вы спросите: Вэл, а в чем собственно проблема то а?
А проблема начинается в декораторах, возможно я еще не до конца в них разобрался, но суть в том, что они замещают тело одной функции на тело другой, включая параметры, в C# насколько я понимаю для этого есть делегаты.
Так вот...
Пишу я тут как то телеграмм бота и решаю загнать весь функционал в класс, который называется BotI к примеру, и пытаюсь использовать aiogram. А в этой библиотеке, в классе Dispatcher куча декораторов, которые отвечают за отправку, редактирование, удаление сообщений и подобный функционал. Так вот, чтобы данные декораторы работали, нужно отправлять в новые методы только те параметры, которые соответствуют параметрам декоратора, а мне, чтобы использовать данные из моего замечательного BotI нужно отправить в новый метод декоратора self. соответственно все ломается.
class BotI:
chats:dict[int,ChatI]
token:str
bot:Bot
dp = Dispatcher()
def __init__(self,Token:str) -> None:
self.token = Token
self.bot = Bot(token=self.token)
async def start(self):
await self.dp.start_polling(self.bot)
def stop(self):
self.dp.stop_polling()
Ну вот к примеру мне нужно записывать чаты, в которых находится бот и в который хоть кто-то написал /start, я сделал бы как то вот так:
@dp.message(CommandStart())
async def command_start_handler(self,message: Message) -> None:
if message.chat.id not in self.chats:
self.chats[message.chat.id] = ChatI(message.chat.id)
Но тут то и зарыта гниющая собака... нельзя мне self отправлять так как декоратор ломается...
*this в последних версиях C# вовсе упрощается и убирается из написания, компилятор сам понимает, чью переменную он использует