2010-06-29 5 views
12

Ich habe gerade zu lange auf einen Fehler wie folgt aus:Python: Kann eine Klasse Clients verbieten, neue Attribute zu setzen?

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


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

ich eine Klasse mit einem Attribut haben. Ich versuchte es einzustellen und fragte mich, warum es keinen Effekt hatte. Dann ging ich zurück zur ursprünglichen Klassendefinition und sah, dass das Attribut etwas anderes genannt wurde. Daher habe ich ein neues Attribut erstellt/gesetzt, anstatt das, was gemeint ist.

Erstens, ist das nicht genau die Art von Fehler, die statisch typisierte Sprachen verhindern sollen? Was ist in diesem Fall der Vorteil der dynamischen Typisierung?

Zweitens, gibt es einen Weg, ich könnte dies bei der Definition Odp verboten haben, und damit mir die Mühe erspart?

+1

Mögliche Duplikate: http://StackOverflow.com/Questions/3079306/How-to-protect-againt-types-when-setting-value-for-class-Members – detly

Antwort

16

Sie können eine __setattr__ Methode zur Umsetzung - das ist viel robuster als die __slots__, die häufig für den Zweck (zum Beispiel missbraucht wird, __slots__ ist automatisch „verloren“, wenn die Klasse von vererbt wird, während __setattr__ überlebt, es sei denn explizit außer Kraft gesetzt).

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__)) 

Sie werden dafür sorgen, müssen die hasattr für die Namen gelingt Sie zum Beispiel in der Lage sein zu setzen, tun wollen, indem Sie die Attribute auf Klassenebene Einstellung oder durch object.__setattr__ in Ihrem __init__ Methode eher als direkte Attributzuweisung. (Um das Setzen von Attributen auf einer Klasse statt seiner Instanzen zu verbieten, müssen Sie eine benutzerdefinierte Metaklasse mit einer ähnlichen speziellen Methode definieren).

+0

Warum haben Sie 'TypeError' gewählt? Vielleicht hatte ich zu Unrecht "AttributeError" im Sinn. – n611x007

+2

"unterstützt keine XX-Zuweisung" Nachrichten (z. B. für Artikel) verwenden "TypeError", verwirrender formuliert "hat kein Attribut XX" verwenden "AttributeError", so denke ich, entweder ist OK (obwohl nicht ganz perfekt). –