2013-05-22 5 views
5

Nie wiem, czy mam tutaj dobry projekt, ale mam klasę wywodzącą się z unittest.TestCase i sposób, w jaki ja Po skonfigurowaniu, mój kod będzie dynamicznie wprowadzał do klasy kilka metod test_* przed wywołaniem unittest, aby je uruchomić. Używam do tego setattr. To działa dobrze, ale teraz mam sytuację, w której chcę usunąć metody wcześniej wstrzyknięte i wstrzyknąć nowy zestaw metod. Jak mogę usunąć wszystkie metody w klasie, której nazwy pasują do wzorca test_*?Python - jak mogę dynamicznie usunąć metodę z klasy - tj. Przeciwieństwo setattr

Odpowiedz

14

Nazywa się delattr i jest dokumentowany here.

+0

Czy też "del" nie działa? –

+0

@JasonSperske: Nie, jeśli musisz usunąć atrybut, którego nazwa została obliczona programowo. Możesz użyć tylko 'del', aby usunąć nazwę, którą możesz dosłownie wpisać w kodzie źródłowym. – BrenBarn

+0

@JasonSperske - tytuł mówi "przeciwieństwo setattr", co oznacza, że ​​OP zna nazwę metody jako ciąg ... – mgilson

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

delattr() jest to, co chcesz. Przeprowadź pętlę przez klasę vars() i przetestuj nazwy atrybutów zaczynające się od "test_". Np

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

Radzę przed użyciem dir(), jak będzie to pokazać nazwy z klas nadrzędnych, tak więc nie wszystkie nazwy można uzyskać z dir() może zdefiniowane na klasie jesteś kierowania.

+0

To wygląda dobrze, ale mam 'RuntimeError: słownik zmienił rozmiar podczas iteracji' – jononomo

+0

O tak,' vars() 'jest słownikiem, mimo że używam klawiszy. Pozwól mi to naprawić ... – kindall

+0

'dir (cls)' może? – thkang

0

Jako dodatek do poprzednich odpowiedzi: Jeśli metoda ma zostać usunięty zostaje ponownie wprowadzone, trzeba by usunąć metod klasy i podklasy rodzicem, zarówno:

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 

(lub skorzystać z delattr Odpowiedź @ BrenBarn)

Powiązane problemy