Klassen mit statischen Attributen ?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

Ich gebrauche eine instanzlose Klasse als Objektsammlung,
es sollen aber nur vorgegebene Namen definiert werden koennen.
Leider funktionier da keine __slots__-Anweisung,
da sich diese immer auf Instanzen bezieht.
Fehlgeschlagener Versuch:

Code: Alles auswählen

class Box(object):
  __slots__ = ('erlaubt',)
  def __init__(self):
    raise 'Keine Instanzen bitte!'
#
Box.erlaubt = 2  #definiert 'erlaubt'
Box.verboten = 3  #definiert leider auch 'verboten'
Muss ich nun für jedes erlaubte Objekt
eine Klassenmethode set_erlaubtesobject(cls)
und eine Klassenmethode erlaubtesobject(cls) schreiben?

Edit (Leonidas): Thread "Test-Driven Development" abgesplittet.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Warum musst du Attribute verbieten? Python erwartet von dir, dass du selber aufpasst, dass du nichts setzt. __slots__ ist nicht dafür da, Attribute zu verbieten, sondern um das __dict__ von einem Objekt zu entfernen.

Ansonsten, eine Metaklasse:

Code: Alles auswählen

class Foo(object):
 class __metaclass__(type):
  __slots__ = ['foo']
TUFKAB – the user formerly known as blackbird
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Darf man nachfragen, warum du keine Instanz der Klasse anlegen möchtest? Vielleicht gehst du das Problem ja nur verkehrt an. Soll "Box" nur einmal vorhanden sein, würde sich evtl. ein Singleton anbieten.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

(1) blackbird: Attribute moechte ich gerne verbieten, weil ich mich oft falsch erinnere, welchen Abkürzung ich vor 6 Monaten für einen Begriff ausgewählt habe, und auf falsche Variablen so bald und so kategorisch wie möglich aufmerksam gemacht werden möchte. Vielleicht ist Python wirklich nichts für so zerstreute Menschen wie ich :cry:. Ja, und dein Metaclass-Code stürzt leider ab mit der Meldung "nonempty __slots__ not supported for subtype of 'type' "

(2) EyDu: Ich benutze jetzt die Singleton-Lösung aus "http://snippets.dzone.com/tag/singleton":

Code: Alles auswählen

class Box(object):
  __slots__ = ('erlaubt',)

  def __new__(type):
    if not '_einzige_Instanz' in type.__dict__:
      type._einzige_Instanz = object.__new__(type)
    return type._einzige_Instanz
Warum ich keine Instanzen anlegen wollte? Wohl nur der Einfachheit halber, und weil ich bis vor kurzem annahm, die Singleton-Lösung sei noch komplizierter. Und auch aus Abneigung zur lächerlichen Borg-Lösung, die unter Umständen Millionen von Instanzen mit denselben Eigenschaften anlegt. Es ist schon seltsam, dass eine Sprache wie Python, die auf Eleganz bedacht ist, sich bei einfachen Dingen wie statischen Attributen so schwer tut.
lunar

Goswin hat geschrieben:(1) blackbird: Attribute moechte ich gerne verbieten, weil ich mich oft falsch erinnere, welchen Abkürzung ich vor 6 Monaten für einen Begriff ausgewählt habe, und auf falsche Variablen so bald und so kategorisch wie möglich aufmerksam gemacht werden möchte.
Dafür ist __slots__ nicht da! Wenn du __slots__ für diesen Zweck einsetzt, machst du etwas ganz grundsätzlich falsch.

Um Fehler mit falschen Namen aufzudecken, gibt es Code-Checker wie pylint oder pychecker. Bei größeren Projekten empfiehlt sich sowieso das schreiben von Unittests, die solche Fehler aufdecken.

Und vielleicht sollte man auch mal die eigenen Abkürzungen auf ihren Sinngehalt prüfen, und eventuell lieber aussagekräftige Namen nehmen.

Natürlich ist es ferner auch nie verkehrt, dass eigene Projekt vernünftig zu dokumentieren, so dass man bei eventuellen Fragen in späterer Zeit einfach die eigene Dokumentation durchgehen kann.
Vielleicht ist Python wirklich nichts für so zerstreute Menschen wie ich :cry:.
Python ist schon das richtige für dich, wenn du die richtigen Werkzeuge einsetzt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Goswin hat geschrieben:Attribute moechte ich gerne verbieten, weil ich mich oft falsch erinnere, welchen Abkürzung ich vor 6 Monaten für einen Begriff ausgewählt habe, und auf falsche Variablen so bald und so kategorisch wie möglich aufmerksam gemacht werden möchte.
Hallo Goswin!

Die Lösung deiner Probleme. WingIDE http://wingware.com/. WingIDE hat die beste Codevervollständigung für Python, die ich kenne. Beim Arbeiten mit WingIDE listet es dir z.B. sofort alle Attribute einer Klasse auf. Und wenn ein Attribut, das du eingibst, nicht aufgelistet wird, dann gibt es dieses Ding nicht. Also kannst du schon beim Eingeben des Codes darauf reagieren. Ohne WingIDE würde ich sicher nicht Python programmieren. Ich wäre nur ein Viertel so produktiv. Und wenn du wirklich so bist wie du dich gibst, dann zahlt es sich doppelt und dreifach aus, in WingIDE ein paar Euro zu investieren.

Weiters kannst du mit WingIDE deinen Code sehr komfortabel Schritt für Schritt debuggen.

Ich bin so einer, der nach ein paar Tagen schon nicht mehr weiß, was er in welchem Modul, in welcher Klasse und wie programmiert hat. Ohne eine gute IDE wäre ich komplett aufgeschmissen. Und viele machen den Fehler, dass sie nichts in eine funktionierende IDE für Python investieren. Und dann wundern sie sich, warum sie nicht so schnell auf eine Lösung kommen. Ich wäre *auch* langsam, wenn ich auf die API-Beschreibungen von Modulen angewiesen wäre, anstatt schon während dem Schreiben, Hilfe und Hinweise zu den aktuellen Funktionen und Methoden zu bekommen.

Ich habe auch am Anfang versucht, mit __slots__ die Falschschreibung von Attributnamen zu verhindern. Aber es ist nur ein Workarround, der dich mehr und mehr Zeit kostet, je größer dein Programm wird. Jede kleine Variable, die du an die Klasseninstanz binden willst, musst du während dem Programmieren in die __slots__-Liste nachtragen. Das wird immer umständlicher und umständlicher je größer deine Klassen werden. --> Vergiss es. Verlass dich lieber auf WingIDE, eine bewährte IDE mit der besten Codevervollständigung, die es für Python gibt.

mfg
Gerold
:-)

PS: Und auf diesen Beitrag hin, erwarte ich mir, dass ich die nächste WingIDE-Release gratis bekomme. :mrgreen: Haaaalllooo Wingware! Hört ihr mich?
:lol:
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

gerold hat geschrieben:WingIDE hat die beste Codevervollständigung für Python, die ich kenne.
Da hast du recht. Es ist irgendwie schade, dass die beste IDE für eine freie Sprache eine proprietäre ist. Das ist wohl einer der wenigen Vorteile, die Java gegenüber Python bietet.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

Tja, jetzt ist es schon wieder passiert, dass ich gedankenverloren folgendes geschrieben habe:

Code: Alles auswählen

import random
random.seed = 1  #ungemeldeter Fehler
anstelle von:

Code: Alles auswählen

import random
random.seed(1)
Un da ich die Zufallszahlen nicht sofort überprüft habe, merke ich ziemlich viel später, dass meine Rechnungen nun nicht reproduzierbar sind. Dies ist nur eins von vielen Beispielen wo es besser wäre, alle Attribute einer Klasse von vornherein festzuschreiben.
Ich weiß, dass __slots__ nicht dafür gemacht wurde. Aber wenn es zusätzlich unvorhergesehene Anwendungen findet, ist das doch etwas Gutes, die Umsetzer von __slots__ könnten stolz darauf sein!
BlackJack

Wenn Du das so siehst, solltest Du nicht in Python programmieren.

Den Fehler hätte man mit einem entsprechenden Test ganz schnell gefunden.
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

Blackjack: Ich programmiere nicht deshalb in Python, weil Python perfekt ist oder ich es dafür halte. Ich kenne keine perfekte Programmiersprache, und mit einer Haltung wie du sie mir empfiehlst, könnte ich überhaupt nicht programmieren. Natürlich kann z.B. Java besser kapseln, aber dafür hat Java eben andere Nachteile. Nur, die Nachteile von Python wird man als Pythonprogrammierer doch wohl beim Namen nennen dürfen, und auch die beste Methode suchen dürfen, damit zu leben!
BlackJack

Das Problem ist, dass Du die Vorteile von Python als Nachteile siehst und damit gegen die Sprache programmierst statt mit ihr. Und wenn Du so gar nicht programmieren kannst, dann ist Python eben nicht die richtige Sprache für Dich.

Die beste Methode mit der dynamischen Natur von Python fertig zu werden ist nicht eine statische(re) Sprache daraus zu machen, sondern ein entsprechendes Entwicklungsmodell zu verwenden, zum Beispiel mit Unittests, eventuell sogar "test driven development" zu betreiben.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:dynamischen Natur von Python fertig zu werden
Seltsam, normalerweise werde ich immer fertig wenn ich statische Sprachen verwende, weil eben alle tollen dynamischen Gimmicks nicht mehr gehen. ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
pyStyler
User
Beiträge: 311
Registriert: Montag 12. Juni 2006, 14:24

Hi,

dein problem!
Goswin hat geschrieben:

Code: Alles auswählen

class Box(object):
  __slots__ = ('erlaubt',)
  def __init__(self):
    raise 'Keine Instanzen bitte!'
#
Box.erlaubt = 2  #definiert 'erlaubt'
Box.verboten = 3  #definiert leider auch 'verboten'
Muss ich nun für jedes erlaubte Objekt
eine Klassenmethode set_erlaubtesobject(cls)
und eine Klassenmethode erlaubtesobject(cls) schreiben?
die lösung?

Code: Alles auswählen

>>> class Box(object):
	__slots__ = ('erlaubt')
	def __getattr__(self, value):
		return value

	
>>> b=Box()
>>> b.erlaubt = 2
>>> b.verboten = 3

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    b.verboten = 3
AttributeError: 'Box' object has no attribute 'verboten'
>>> 
Gruss
pyStyler
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

gerold hat geschrieben: Die Lösung deiner Probleme. WingIDE http://wingware.com/.
Was mich an Wing IDE massiv stört, ist diese künstliche Unterscheidung zwischen Personal und Professional. Z.B. Code-Folding nur in der Professional finde ich schon etwas lächerlich. Ansonsten würde mich das schon irgendwie reizen...

Edit (Leonidas): Thread "Test-Driven Development" abgesplittet.
Antworten