Foleosy Foleosy - 1 year ago 34
Python Question

Calling non-static methods from static methods with use of "self"

I am a beginner in Python, so please be... kind?

Anyway, I need use a static method to call another method, which requires the use of "self" (and thus, a normal method I believe). I am working with Telethon, a Python implementation of Telegram. I have tried other questions on SO, but I just can't seem to find a solution to my problem.

An overview of the program (please correct me if I'm wrong):

1) interactive_telegram_client is a child class of telegram_client, and it creates an instance.

#interactive_telegram_client.py
class InteractiveTelegramClient(TelegramClient):
super().__init__(session_user_id, api_id, api_hash, proxy)


2) When the InteractiveTelegramClient runs, it adds an update_handler
self.add_update_handler(self.update_handler)
to constantly check for messages received/sent, and prints it to screen

#telegram_client.py
def add_update_handler(self, handler):
"""Adds an update handler (a function which takes a TLObject,
an update, as its parameter) and listens for updates"""
if not self.sender:
raise RuntimeError(
"You should connect at least once to add update handlers.")

self.sender.add_update_handler(handler)

#interactive_telegram_client.py
@staticmethod
def update_handler(update_object):
try:
if type(update_object) is UpdateShortMessage:
if update_object.out:
print('You sent {} to user #{}'.format(update_object.message,
update_object.user_id))
else:
print('[User #{} sent {}]'.format(update_object.user_id,
update_object.message))


Now, my aim here is to send back an auto-reply message upon receiving a message. Thus, I think that adding a call to method
InteractiveTelegramClient.send_ack(update_object)
in the
update_handler
method would serve my needs.

#interactive_telegram_client.py
def send_ack(self, update_object):
entity = update_object.user_id
message = update_object.message
msg, entities = parse_message_entities(message)
msg_id = utils.generate_random_long()

self.invoke(SendMessageRequest(peer=get_input_peer(entity),
message=msg,random_id=msg_id,entities=entities,no_webpage=False))


However, as you can see, I require the
self
to invoke this function (based on the readme, where I assume
client
to refer to the same thing as
self
). Since the method
update_handler
is a static one,
self
is not passed through, and as such I cannot invoke the call as such.

My possible strategies which have failed include:

1) Instantiating a new client for the auto-reply
- Creating a new client/conversation for each reply...

2) Making all the methods non-static
- Involves a tremendous amount of work since other methods modified as well

3) Observer pattern (sounds like a good idea, I tried, but due to a lack of skills, not succeeded)

I was wondering if there's any other way to tackle this problem? Or perhaps it's actually easy, just that I have some misconception somewhere?

Forgot to mention that due to some restrictions on my project, I can only use Telethon, as opposed to looking at other alternatives. Adopting another library (like an existing auto-reply one) is allowed, though I did not really look into that since merging that and Telethon may be too difficult for me...

Answer Source

based on the readme, where I assume client to refer to the same thing as self

Correct, since the InteractiveTelegramClient subclasses the TelegramClient and hence, self is an instance of the extended client.

Instantiating a new client for the auto-reply - Creating a new client/conversation for each reply

This would require you to create another authorization and send another code request to login, because you can't work with the same *.session at the same time.

Making all the methods non-static - Involves a tremendous amount of work since other methods modified as well

It doesn't require such amount of work. Consider the following example:

class Example:
    def __init__(self, a):
        self.a = a

    def do_something(self):
        Example.other_method()

    @staticmethod
    def other_method():
        print('hello, world!')

Is equivalent to:

class Example:
    def __init__(self, a):
        self.a = a

    def do_something(self):
        self.other_method()

    @staticmethod
    def other_method():
        print('hello, world!')

It doesn't matter whether you use self. or the class name to refer to a static method from within the class. Since the InteractiveClientExample already uses self., all you would have to do would be changing:

@staticmethod
def update_handler(update_object):

for

def update_handler(self, update_object):

For more on the @staticmethod decorator, you can refer to the docs.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download