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