Aaa
Aaa

Reputation: 134

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...

Upvotes: 0

Views: 929

Answers (1)

Lonami
Lonami

Reputation: 7096

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.

Upvotes: 1

Related Questions