Python - как я могу динамически удалить метод из класса-т. е. напротив setattr

Я не знаю, есть ли у меня хороший дизайн здесь, но у меня есть класс, производный от unittest.TestCase и то, как я его настроил, мой код будет динамически вводить кучу test_* методы в класс перед вызовом unittest для запуска через него. Я использую setattr для этого. Это работает хорошо, но теперь у меня есть ситуация, в которой я хочу удалить методы, которые я ранее вводил, и ввести новый набор методов. Как удалить все методы в классе, имена которых соответствовать шаблону test_*?

4 ответов


Это называется delattr и документируется здесь.


>>> class Foo:
    def func(self):
        pass
...     
>>> dir(Foo)
['__doc__', '__module__', 'func']
>>> del Foo.func
>>> dir(Foo)
['__doc__', '__module__']

delattr() это то, что вы хотите. Петля через vars() класса и теста для имен атрибутов, начиная с "test_". Е. Г.,

@classmethod
def remove_test_methods(cls):
    for name in list(vars(cls)):
        if name.startswith("test_") and callable(getattr(cls, name)):
            delattr(cls, name)

Я бы не советовал использовать dir(), как это покажет вам имена из родительских классов, так что не все имена, которые вы получаете от dir() может быть определено в классе, на который вы нацелены.


в дополнение к предыдущим ответам: Если метод, который будет удален, будет повторно реализован, вам придется удалить методы подкласса и родительского класса, оба:

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

(или использовать delattr ответа @BrenBarn)