Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a python class has particular method or not?

class C(Test):
    def __init__(self):
        print "in C init"
        super(C, self).__init__()

    def setup(self):
        print "\tin C setup"

    def runtest(self):
        print "\t\tin C runtest"

    def teardown(self):
        print "\t\t\tin C teardown"

I have such classes in different modules. For eg class A,B,C etc.. In one module I'm considering only classes who have setup and teardown methods. Suppose Class A doesn't have setup method, I don't want to consider it for further parth of my program where I'm building list of classes having setup and runtest module. Is there any python function I can use for the same? What is the correct way to deal with this problem?

like image 936
NikAsawadekar Avatar asked Feb 06 '26 17:02

NikAsawadekar


2 Answers

I would argue this is a case for an abstract base class.

class Test(metaclass=ABCMeta):
    @abstractmethod
    def setup(self):
        ...

    @abstractmethod
    def teardown(self):
        ...

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Test:
            if (any("setup" in B.__dict__ for B in C.__mro__) and 
               any("teardown" in B.__dict__ for B in C.__mro___)):
                return True
        return NotImplemented

This defines the type Test, and a __subclasshook__ function that checks if a class defines setup() and teardown(). This means any such class will be treated as a subclass of Test - that is issubclass() will return True for issubclass(C, Test).

Of course, you could just do the check manually using the same methodology as the __subclasshook__ function, but abstract base classes provide a nice (and standard) way to define the contract you want fulfilled.

like image 55
Gareth Latty Avatar answered Feb 09 '26 09:02

Gareth Latty


You can use hasattr and callable on the classes themselves (classes are objects afterall), i.e. something like

if hasattr( C, 'setup' ) and callable( C.setup ):
      classes_with_setup.append(C)

or, in terms of a list comprehension

classes_with_setup=[ U for U in [A,B,C...] if hasattr(U,'setup') and callable(U.setup)]

to setup your list of classes with those features.

This methodology does detect inheritance:

In [1]: class A(object):
   ...:     def f(self):
   ...:         print 'hi'
   ...:         

In [2]: class B(A):
   ...:     pass
   ...: 

In [3]: hasattr(A,'f')
Out[3]: True

In [4]: hasattr(B,'f')
Out[4]: True

In [5]: hasattr(B,'f') and callable(B.f)
Out[5]: True
like image 25
Dave Avatar answered Feb 09 '26 10:02

Dave



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!