I don't know if I have a good design here, but I have a class that is derived from unittest.TestCase and the way I have it set up, my code will dynamically inject a bunch of test_*
methods into the class before invoking unittest to run through it. I use setattr
for this. This has been working well, but now I have a situation in which I want to remove the methods I previously injected and inject a new set of methods. How can I remove all the methods in a class whose names match the pattern test_*
?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
It's called delattr
and is documented here.
回答2:
>>> class Foo:
def func(self):
pass
...
>>> dir(Foo)
['__doc__', '__module__', 'func']
>>> del Foo.func
>>> dir(Foo)
['__doc__', '__module__']
回答3:
delattr()
is what you want. Loop through vars()
of the class and test for attribute names starting with "test_"
. E.g.,
@classmethod
def remove_test_methods(cls):
for name in list(vars(cls)):
if name.startswith("test_") and callable(getattr(cls, name)):
delattr(cls, name)
I'd advise against using dir()
, as this will show you names from your parent classes as well, so not all the names you get from dir()
may defined on the class you're targeting.
回答4:
As an addition to the previous answers: If the method to be deleted is re-implemented, you'd have to delete the subclass and parent class methods, both:
class A:
def method(self):
print("TestA")
class B(A):
def method(self):
A.method(self)
print("TestB")
instance = B()
instance.method() # will call B.method()
del B.method
instance.method() # will now call A.method()
del A.method
instance.method() # will now raise AttributeError
(Or use delattr
of @BrenBarn's answer)