How to check if a python class has particular meth

2019-08-07 01:12发布

问题:

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?

回答1:

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.



回答2:

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


回答3:

You can use getattr and callable methods

setup_method = getattr(your_object, "setup_method", None)
if callable(setup_method):
    setup_method(self.path.parent_op)

First check if the object has an attribute called "setup_method" then check it that attribute is a method and then call it.