2013-05-22 1 views
5

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

ответ

14

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

+0

Не будет 'del' также работать? –

+0

@JasonSperske: Нет, если вам нужно удалить атрибут, имя которого вычисляется программно. Вы можете использовать 'del' только для удаления имени, которое вы можете буквально ввести в исходный код. – BrenBarn

+0

@JasonSperske - название говорит «напротив setattr», подразумевая, что OP знает имя метода как строку ... – mgilson

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

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() может определить на классе вы ориентируетесь.

+0

Это выглядит хорошо, однако я получил «RuntimeError: измененный размер слова во время итерации» – jononomo

+0

О да, 'vars()' - словарь, хотя я просто использую ключи. Позвольте мне исправить это ... – kindall

+0

'dir (cls)' может быть? – thkang

0

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

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 ответ)