如何检查Python类是否具有特定方法?
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"
我在不同的模块里有一些类,比如类 A
、B
、C
等等。在一个模块中,我只考虑那些有设置(setup)和拆卸(teardown)方法的类。假设类 A
没有设置方法,我就不想在我的程序后续部分考虑它,因为我正在建立一个包含有设置和运行测试(runtest)模块的类的列表。有没有什么 Python 函数可以用来解决这个问题?处理这个问题的正确方法是什么?
3 个回答
2
你可以使用 getattr
和 callable
这两个方法。
setup_method = getattr(your_object, "setup_method", None)
if callable(setup_method):
setup_method(self.path.parent_op)
首先,检查这个对象是否有一个叫做 "setup_method
" 的属性,然后再检查这个属性是不是一个方法,最后再调用它。
4
你可以在类本身上使用 hasattr
和 callable
,因为类本身也是对象。也就是说,你可以这样做:
if hasattr( C, 'setup' ) and callable( C.setup ):
classes_with_setup.append(C)
或者,用列表推导的方式来写:
classes_with_setup=[ U for U in [A,B,C...] if hasattr(U,'setup') and callable(U.setup)]
这样就可以设置一个包含这些特性的类的列表。
这种方法可以检测到继承关系:
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
5
我认为这是一个使用抽象基类的好例子。
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
这里定义了一个类型叫做Test
,还有一个__subclasshook__
函数,这个函数用来检查一个类是否定义了setup()
和teardown()
这两个方法。这意味着任何符合条件的类都会被当作Test
的子类来看待——也就是说,调用issubclass(C, Test)
时会返回True
。
当然,你也可以手动检查,使用和__subclasshook__
函数相同的方法,但抽象基类提供了一种很好的(而且是标准的)方式来定义你想要的契约。