Search code examples
pythonabstract-class

How to call non abstract method in a abstract class?


I have an abstract class in python and want to call non-abstract methods in it. Is it possible to do it?

from abc import ABC, abstractmethod
class MyAbstract(ABC):

# Can I call method get_state() from get_current() ?
def get_state():
   get_current()  # gives me error?

def get_current():

@abstractmethod
def get_time():

I have another python file, Temp.py implement this interface. In Temp.py, I call the get_state using MyAbstract.get_state(), I get the error stating that get_current() is undefined.

Not sure why.

Any help is appreciated.


Solution

  • In general, all methods have a namespace which is the class or object they're attached to. If you have an instance of a class floating around (e.g. self, most of the time), you can call methods on that instance that automatically pass the instance itself as the first parameter - the instance acts as the namespace for an instance method.

    If you're using a class method or a static method, then the namespace is almost always going to be the class they're attached to. If you don't specify a namespace, then python assumes that whatever function you're trying to call is in the global namespace, and if it isn't, then you get a NameError.

    In this case, the following should work for you:

    class MyAbstract(ABC):
        def get_current():
            print("current")
    
        def get_state():
            MyAbstract.get_current()
    
        @abstractmethod
        def get_time():
            pass
    

    You can just imagine that you have a little invisible @staticmethod decorator hanging above get_current() that marks it as such. The problem with this is that now you don't get to change the behavior of get_current() in subclasses to affect change in get_state(). The solution to this is to make get_state() a class method:

        @classmethod
        def get_state(cls):
            cls.get_current()
    

    Calling a static method uses identical syntax to calling a class method (in both cases you would do MyAbstract.get_state(), but the latter passes the class you're calling it on as the first argument. You can then use this class as a namespace to find the method get_current() for whatever subclass has most recently defined it, which is how you implement polymorphism with method that would otherwise be static.