6

I have the following simplified scheme:

class NetworkAnalyzer(object):
    def __init__(self):
       print('is _score_funct implemented?')

    @staticmethod
    def _score_funct(network):
        raise NotImplementedError

class LS(NetworkAnalyzer):
    @staticmethod
    def _score_funct(network):
        return network

and I am looking for what I should use instead of print('is _score_funct implemented?') in order to figure out if a subclass has already implemented _score_funct(network) or not.

Note: If there is a more pythonic/conventional way of structuring the code, I would also appreciate its mention. The reason I defined it this way is, some NetworkAnalyzer subclasses have _score_funct in their definition, and the ones that dont have it will have different initialization of variables although they will have the same structure

7
  • 5
    abstract methods? stackoverflow.com/questions/4382945/abstract-methods-in-python Commented Apr 18, 2018 at 15:09
  • Well you could take a look at the AST and look if there is only a single raise statement and the only constant is NotImplementedError. Commented Apr 18, 2018 at 15:13
  • 1
    I would suggest you figure out the minimal behavior for each subclass and turn that into an abstract base class. See the abc docs . Research Liskov Substitution Principle . Commented Apr 18, 2018 at 15:16
  • Why not just not implement the function in the base class and in __init__ use getattr() and callable() to check if it exists and can be called? Commented Apr 18, 2018 at 15:16
  • I havent used abstract methods as I had little understanding of metaclasses. I will read the documentation to have it more conventional. By then, I have tried @Jean-FrançoisFabre's answer and it works Commented Apr 18, 2018 at 15:18

2 Answers 2

4

Use an abstract base class and you won't be able to instantiate the class unless it implements all of the abstract methods:

import abc

class NetworkAnalyzerInterface(abc.ABC):
    @staticmethod
    @abc.abstractmethod
    def _score_funct(network):
        pass

class NetworkAnalyzer(NetworkAnalyzerInterface):
    def __init__(self):
        pass

class LS(NetworkAnalyzer):
    @staticmethod
    def _score_funct(network):
        return network

class Bad(NetworkAnalyzer):
    pass

ls = LS()   # Ok
b = Bad()   # raises TypeError: Can't instantiate abstract class Bad with abstract methods _score_funct
Sign up to request clarification or add additional context in comments.

2 Comments

Do I need the NetworkAnalyzerInterface in this example by any conventional reason or can I just bypass it by NetworkAnalyzer(abc.ABC)
You can probably just make NetworkAnalyzer itself the abstract class in this case. I would just prefer to keep interface and implementation code separate although in the example I ended up with there's no implementation code.
2

I'm not a metaclass/class specialist but here's a method that works in your simple case (not sure it works as-is in a complex/nested class namespace):

To check if the method was overridden, you could try a getattr on the function name, then check the qualified name (class part is enough using string partitionning):

class NetworkAnalyzer(object):
    def __init__(self):
        funcname = "_score_funct"
        d = getattr(self,funcname)
        print(d.__qualname__.partition(".")[0] == self.__class__.__name__)

if _score_funct is defined in LS, d.__qualname__ is LS._score_funct, else it's NetworkAnalyzer._score_funct.

That works if the method is implemented at LS class level. Else you could replace by:

d.__qualname__.partition(".")[0] != "NetworkAnalyzer"

Of course if the method is overridden with some code which raises an NotImplementedError, that won't work... This method doesn't inspect methods code (which is hazardous anyway)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.