2010-06-29 15 views
12

Właśnie spędziłem zbyt długo na błąd jak poniżej:Python: Czy klasa może zakazać klientom ustawiania nowych atrybutów?

>>> class Odp(): 
    def __init__(self): 
     self.foo = "bar" 


>>> o = Odp() 
>>> o.raw_foo = 3 # oops - meant o.foo 

Mam klasy z atrybutem. Próbowałem to ustawić i zastanawiałem się, dlaczego nie przyniosło to efektu. Następnie powróciłem do pierwotnej definicji klasy i zobaczyłem, że atrybut został nazwany czymś nieco innym. Tak więc tworzyłem/ustawiałem nowy atrybut zamiast tego, który ma być.

Po pierwsze, czy nie jest to dokładnie ten typ błędu, który ma zapobiegać w statycznie napisanych językach? W takim razie jaka jest zaleta pisania dynamicznego?

Po drugie, czy istnieje sposób, w jaki mogłem zakazać tego podczas definiowania Odp, a tym samym uratowałem sobie kłopot?

+1

Możliwy duplikat: http://stackoverflow.com/questions/3079306/how-to-protect-againt-typos-when-setting-value-for-class-members – detly

Odpowiedz

16

można zaimplementować metodę __setattr__ do celu - to jest znacznie bardziej wytrzymałe niż __slots__ który jest często nadużywane do celów (np __slots__ jest automatycznie „stracone”, gdy klasa jest dziedziczona od, natomiast __setattr__ przetrwa chyba jawnie nadpisane).

def __setattr__(self, name, value): 
    if hasattr(self, name): 
    object.__setattr__(self, name, value) 
    else: 
    raise TypeError('Cannot set name %r on object of type %s' % (
        name, self.__class__.__name__)) 

Musisz upewnić się, że hasattr powiedzie dla nazw zrobić chcą być w stanie ustalić, na przykład poprzez ustawienie atrybuty na poziomie klasy lub za pomocą object.__setattr__ w swojej metodzie __init__ raczej niż bezpośrednie przypisanie atrybutów. (Aby zabronić ustawiania atrybutów w klasie klasy zamiast ich instancji, musisz zdefiniować niestandardową metaklasę o podobnej specjalnej metodzie).

+0

dlaczego wybrałeś 'TypeError'? Może błędnie, miałem na myśli 'AttributeError'. – n611x007

+2

"nie obsługuje komunikatów XX przypisania" (np. Dla pozycji) używaj 'TypeError', bardziej myląco sformułowanego" nie ma atrybutu XX "używają' AttributeError', więc myślę, że albo jest OK (choć nie całkiem doskonały). –

Powiązane problemy