2010-06-20 5 views
5

Betrachten Sie das folgende Beispiel:Wie kann man gegen Tippfehler schützen, wenn man den Wert für die Klassenmitglieder einstellt?

class A(): 
    def __init__(self): 
     self.veryImportantSession = 1 

a = A() 
a.veryImportantSession = None # ok 

# 200 lines below 
a.veryImportantSessssionnnn = 2 # I wanna exception here!! It is typo! 

Wie könnte ich es so machen, dass eine Ausnahme ausgelöst wird, wenn ich versuche, ein Mitglied zu setzen, die in __init__ nicht gesetzt ist?

Code oben wird nicht fehlschlagen, wenn es ausgeführt wird, aber gibt mir eine schöne Zeit, um die Probleme zu debuggen.

Wie bei str:

>>> s = "lol" 
>>> s.a = 1 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'str' object has no attribute 'a' 

Dank!

+2

Sie können bessere Antworten erhalten, wenn Sie auch erklären, warum Sie dies tun möchten. – detly

+3

Versuche, Python in Java/C++ zu verwandeln, haben mich immer auf die gleiche Weise verwirrt wie das Singleton-Anti-Pattern. Wenn du nicht mehr als ein Foo willst, instanziiere es nicht, wenn du nicht willst, dass 'a.y' es nicht bindet. Wenn Sie Ihren Bibliotheksbenutzer auf mysteriöse Weise einschränken möchten, tun Sie etwas falsch. – msw

+0

ok, wahrscheinlich ist das nicht, was ich wirklich will. Das Problem besteht darin, dass Objekte der Klasse A an vielen Stellen des Codes verwendet werden und Element "a" von großer Bedeutung ist. Lassen Sie uns sagen, dass es richtiger Name ist "superImportantSession". Wenn ich einen Tippfehler an einer Codestelle gemacht habe und "a.superImportantSesssssion = 1" geschrieben habe, bekomme ich keinen Fehler, wenn diese Codezeile ausgeführt wird. Aber ich werde Spaß haben, den Fehler zu debuggen. Wahrscheinlich muss ich setSession/getSession oder etw so verwenden. – lstipakov

Antwort

6

Sie könnten __setattr__ überschreiben, um nur Attributnamen aus einer definierten Liste zuzulassen.

class A(object): 
    def __setattr__(self, name, value): 
     allowed = ('x',) 
     if name in allowed: 
      self.__dict__[name] = value 
     else: 
      raise AttributeError('No attribute: %s' % name) 

Im Betrieb:

>>> a = A() 
>>> a.x = 5 
>>> a.other = 5 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "myc.py", line 7, in __setattr__ 
    raise AttributeError('No attribute: %s' % name) 
AttributeError: No attribute: other 

Doch wie msw kommentiert, versucht zu Python mehr wie Java zu machen verhalten oder C++ ist in der Regel eine schlechte Idee und führt viele der Vorteile, den Python zu verlieren bietet. Wenn Sie Bedenken haben, Tippfehler zu vermeiden, die Sie verpasst haben, können Sie viel Zeit damit verbringen, Komponententests für Ihren Code zu schreiben, anstatt zu versuchen, die Verwendung Ihrer Klassen zu sperren.

+2

Vereinbart mit Unit-Tests, aber ist es die beste Art, Tippfehler zu vermeiden? – lstipakov

+1

Eine Kombination aus Komponententests und anderen Arten von automatisierten Tests. z.B. Anhand eines Beispiels aus den Kommentaren zur Frage selbst, ob es einen Test gegeben hat, der den Status Ihrer Sitzung vor und nach einer Operation überprüft hat, können Sie feststellen, ob "superImportantSession" nicht korrekt eingestellt wurde. – mikej

+1

@Stipa: Ich würde es sagen, da Sie zwei gleiche Tippfehler machen müssten. So etwas wie Tippfehler bei der Deklaration und beim Setzen von Variablen. – Almad

1

Sie können eine Klassenvariable namens __slots__ definieren. Weitere Informationen finden Sie unter Language Reference.

__slots__ arbeiten nur in neuen Stilklassen, so dass Sie class A(object) anstelle von class A in diesem Beispiel benötigen.

class A(object): 
    __slots__ = ['x'] 
    def __init__(self): 
     self.x = 1 

>>> a = A() 
>>> a.x = 2 
>>> a.y = 2 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'A' object has no attribute 'y' 
+2

'__slots__' dient zur Speicheroptimierung und sollte nur sehr selten verwendet werden. Verwenden Sie es zum "Schutz vor Tippfehlern" missbrauchen es - bitte empfehlen Sie es nicht für diesen Zweck. Anfänger werden nicht verstehen, was sie kaputt machen - zum Beispiel, dass dies leise Schwächen gebrochen hat. –

2

Der beste Weg, um gegen Fehler zu schützen, ist ein Werkzeug wie pyflakes oder pylint verwenden - diese werden Ihren Code durchlaufen und lassen Sie wissen, wenn Sie eine Variable a.superImportantSesssssionnnn haben, die nicht immer und immer wieder verwendet wird, wie und viele andere Dinge.

Wenn Sie darauf bestehen, es im Code zu tun haben Sie zwei Möglichkeiten:

  • (ab) verwenden __slots__ - der primäre Zweck der __slots__ Speicheroptimierung für die damalige Zeit, wenn Sie Hunderte, Tausende haben wird, oder Millionen von Objekten und Sie müssen die Fußabdrücke Ihrer Objekte so klein wie möglich halten. Wenn Sie diese Route gehen, sollten Sie sicherstellen und __weakref__ als einen der zulässigen Namen einschließen, damit weak references weiter funktioniert.

  • (ab) verwenden __setattr__ - der primäre Zweck der __setattr__ ist Code zu ermöglichen, zu laufen zu validieren, zu manipulieren, oder nehmen Sie sonst die angegebenen Daten und legen Sie sie in das richtige Format für die Speicherung

Nochmals, die beiden oben genannten Optionen sind nicht als Rechtschreibprüfung gedacht, und Ihre Bemühungen, die Nützlichkeit Ihres Codes einzuschränken, indem Sie jeden möglichen Attributnamen außer den wenigen, die Sie selbst verwenden, missachten, werden möglicherweise nicht gewürdigt um einen Anwendungsfall zu unterstützen, den Sie nicht erwartet haben.

Verwandte Themen