'Decorators in class methods
I'm trying to apply decorator from another class on method in my class... it is my implementation of this Telegram API wrapper library: https://github.com/eternnoir/pyTelegramBotAPI
But in my example want to use it not from script - but as method of class like that:
class Bot:
def __init__(self, key):
self.key = key
self.bot=telebot.TeleBot(key)
def start(self):
self.bot.polling()
# Handle '/start' and '/help'
@self.bot.message_handler(commands=['help', 'start'])
def send_welcome(self,message):
self.bot.reply_to(message, """\
Hi there, I am EchoBot. \
I am here to echo your kind words back to you. \
Just say anything nice and I'll say the exact same thing to you!\
""")
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@self.bot.message_handler(func=lambda message: True)
def echo_message(message):
self.bot.reply_to(message, message.text)
All self are highlighted ... and certainly not working - will be glad if someone can explain what im doing wrong?
The original example trying to customize is:
import telebot
bot = telebot.TeleBot("TOKEN")
@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
bot.reply_to(message, "Howdy, how are you doing?")
@bot.message_handler(func=lambda message: True)
def echo_all(message):
bot.reply_to(message, message.text)
bot.polling()
Solution 1:[1]
for those who might need it - solution i found - was to put the functions inside Ctor - and not to apply decorators to class methods .... :
class Bot:
def __init__(self, key,greting):
self.key = key
self.bot=telebot.TeleBot(key)
self.greting=greting
# Handle '/start' and '/help'
@self.bot.message_handler(commands=['help', 'start'])
def send_welcome(self, message):
self.bot.reply_to(message,self.greting )
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@self.bot.message_handler(func=lambda message: True)
def echo_message(message):
self.bot.reply_to(message, message.text)
def start(self):
x = threading.Thread(name=self.greting, target=self.bot.polling,)
x.start()
Solution 2:[2]
self though a keyword is more of a placeholder variable name for the 1st argument for all methods that is always the instance object (except for classmethod where 1st argument is the class itself and staticmethod where there is neither)
For any method, even if you use this instead if self as 1st argument of any method, you can access all the object attributes as this.foo or methods as this.bar().
So technically, you don't have access to the object outside any method. The decorator is at the outer most level where you cannot access object (which is passed only to methods as the 1st argument)
A complex and unnecessary workaround I can think of is to write a static method that will help you catch the self object from argument and then access it's message_handler
Solution 3:[3]
I think that proper method is to use lambda functions. You can pass more than one parameter to it and get self from outer scope.
So, i finished with next sample
import telebot
class Telegram:
def __init__(self, token):
self.channel = telebot.TeleBot(token, parse_mode=None)
start_dict = dict(
function=lambda msg, obj=self: obj.start_handler(msg),
filters=dict(
commands=["start"],
)
)
self.channel.add_message_handler(start_dict)
self.channel.polling()
def start_handler(self, message):
print("START command")
test = Telegram("your-token-here")
You can run it from console and it will print START command every time you send /start to it.
Solution 4:[4]
You should set object of TeleBot() in method start().
import telebot
from decouple import config as key
class TelegramBot():
def bot(self):
bot = telebot.TeleBot(key('token'))
@bot.message_handler(commands=['start'])
def start(message):
bot.send_message(message.chat.id, "Sup, Sani :)")
bot.polling(none_stop=True)
TelegramBotSpot().bot()
Solution 5:[5]
class Variaveis:
def __init__(self):
self.bot = telebot.TeleBot(token='')
@self.bot.message_handler(commands=["start"])
def _process_command_start(message):
self.process_command_start(message)
self.bot.polling(none_stop=True, timeout=123)
#----------------------------------------------------------------------------------------------------------------#
# Começando a programar :
def process_command_start(self, message):
self.bot.send_message(message.chat.id, 'ola mundo')
Variaveis()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Kamornik Cola |
| Solution 2 | dumbPy |
| Solution 3 | Mullo |
| Solution 4 | Sani4 |
| Solution 5 | aaossa |
