Keine Konstanten in Python: warum?

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.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ein paar Anmerkungen: Wie die meisten funktionalen Sprachen, sind bei Scala Variablen konzeptuell keine Zellen, in die man Dinge tut, sondern Namen für Teilausdrücke. Haben diese Ausdrücke keinen Seiteneffekt, kann man sogar noch nicht einmal erkennen, wann und wie oft sie berechnet werden. Dann sind es Konstanten. Ein schauer Compiler sollte sie nämlich nur 1x berechnen und dann statt der Variable ihren Wert und nicht den Teilausdruck einsetzen.

Ich persönlich finde es eigentlich recht elegant, dass bei Scala `val` und `var` so ähnlich aussehen. In den Code gesprenkelte `final`-Modifikatoren wie bei Java stören dagegen meine Ästhetik.

Python hat ein anderes (klassisches) Ausführungsmodell. Hier basiert alles auf Dictionaries und Veränderbarkeit ist der Normalfall (und nicht die Ausnahme wie bei funktionalen Sprachen). Konstanten wären denkbar, müssten aber zur Laufzeit vom Interpreter geprüft werden, bräuchten irgendwie Syntax und es war GvR offenbar nicht den Aufwand wert.

Letztlich ist eine Konstanten-Deklaration ja ein Hinweis für den Entwickler und damit in erster Linie Dokumentation (einer Annahme, die von einem Compiler überprüft werden kann). In Python muss man einfach auf die Prüfung durch den Compiler verzichten. Dafür gibt es (wie schon gesagt) andere Tools, die versuchen, ein paar statische Informationen aus Python Code zu extrahieren.

Ruby hat sehr wohl Konstanten. Variablen, die mit einem Großbuchstaben beginnen, gelten als konstant und es gibt eine Warnung des Interpreters, wenn man diesen ein zweites Mal etwas zuweist.

Übrigens, wer `final` in Java im Glauben benutzt, dem JIT-Compiler einen Gefallen zu tun, der kann das gleich lassen. Hotspot ist viel besser daran, konstante Teilausdrücke auch über mehrere Inline-Stufen zu finden und zu optimieren und Methoden zu de-virtualisieren, als das der Programmierer kann. Daher sollte `final` nur dann benutzt werden, wenn man dem Mitentwickler signalisieren will, dass eine Variable nicht als veränderbar gedacht ist, eine Methode oder Klasse nicht für Vererbung vorgesehen ist oder wenn inner classes es aus syntaktischen Gründen erfordern. Aber niemals, weil man glaubt, der Code würde effizienter.

Letztlich sind alle statischen Typdeklarationen (zu denen auch gehört, etwas als unveränderbar zu kennzeichnen) explizite Redundanzen, die helfen, Fehler zu finden, wenn man implizit im Code vorhandene Annahmen nicht einhält. Dumm nur, dass manchmal derartige statische Typdeklarationen den Code schwerer verständlich machen, als wenn sie fehlen würden. Und genau das ist dann das Argument gegen statische und für dynamische Typisierung.

Stefan
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Code: Alles auswählen

import __builtin__
from types import ModuleType

class ConstNameError(NameError):
    pass

class ConstNameModule(ModuleType):
    def __setattr__(self, name, value):
        if name.isupper() and hasattr(self, name):
            raise ConstNameError("Tried to reset const name")

        ModuleType.__setattr__(self, name, value)

_old_import = __import__
def const_name_import(*args, **kwargs):
    module = _old_import(*args, **kwargs)
    const_name_module = ConstNameModule(module.__name__)

    const_name_module.__dict__.clear()
    const_name_module.__dict__.update(module.__dict__)

    return const_name_module
__builtin__.__import__ = const_name_import
Funktioniert nur nach vollendetem Import. Näher käme man nur dann dran, wenn man imp.load_module() den eigenen Modul-Typ übergeben könnte, da die C Implementation von imp.load_module() in Objects/import.c PyModule_New() direkt aufruft, und man somit keine Möglichkeit hat, da irgendwas mit zb. dem types Module zu drehen. Oder man schreibt den kompletten Import-Mechanismus neu, was im Grunde gehen sollte.
philistion
User
Beiträge: 108
Registriert: Sonntag 7. Februar 2010, 14:16

sma hat geschrieben:Ich persönlich finde es eigentlich recht elegant, dass bei Scala `val` und `var` so ähnlich aussehen. In den Code gesprenkelte `final`-Modifikatoren wie bei Java stören dagegen meine Ästhetik.
Also ich ziehe Übersichtlichkeit und Verständlichkeit der Ästhetik vor..
sma hat geschrieben:Ruby hat sehr wohl Konstanten.
Ja, hatten wir schon. Eben das wäre bei Python auch nett, also in der Implementierung selbst und nicht per Monkey-Patching.
sma hat geschrieben:Dumm nur, dass manchmal derartige statische Typdeklarationen den Code schwerer verständlich machen, als wenn sie fehlen würden.
Also ich kenne keine Beispiele wo die Verwendung von Konstanten den Code komplexer macht, bei Ruby sind es lediglich Großbuchstaben anstatt Kleinbuchstaben, also nur marginale Differenzen, bei C ist es das kleine Wörtchen "const", ansonsten verhält es sich doch relativ unauffällig, hilft aber im Bedarfsfall Fehlern auf die Schliche zu kommen.
fredistdurstig
User
Beiträge: 13
Registriert: Sonntag 18. Januar 2009, 20:08

Jeder Programmierer bekommt eingehämmert, dass das Verwenden von ziemlich ähnlichen Variablennamen *Pfui* ist. So etwas dann in die Syntax einer Sprache zu gießen ist schon bösartig.
Das stimmt so nicht. Die Variablennamen sind hier ja i und j, die habe ich selbst gewählt. Var und val sind ja quasi nur zusätzliche identifier, die dem Compiler sagen, ob eine Variable konstant ist oder nicht.

Der große Vorteil dieser kurzen und einfachen Schreibweise ist der, dass der Programmierer nicht aus Faulheit auf die Verwendung von Konstanten verzichtet - wie es in Java der Fall sein kann. Schließlich muss an jede Variable ZUSÄTZLICH noch das Wort "final" rangeschrieben werden. In Scala ist der Schreibaufwand jedoch derselbe.
Hmm, wenn schon würde ich const verwenden. val und var ist doch viel zu ähnlich!
Sie sind ähnlich. Allerdings hat man das sehr schnell im Blick. Generell wird in Scala sowieso meist mit Konstanten gearbeitet, var ist eher die Ausnahme.

Auf mein Argument, dass Konstanten Seiteneffekte vermeiden, und daher einen funktionalen Programmierstil fördern, wurde hier nicht eingegangen. Anscheinend ist funktionales Programmieren in Python kein großes Thema?

Das man Konstanten in Python "nachprogrammieren" kann war mir schon klar. Mich wundert nur, dass das so nicht in der Sprache vorhanden ist, da es ja keinen weiteren Aufwand bedeutet hätte. Daher muss es ja auch einen ganz konkreten Grund geben, warum auf Konstanten ganz explizit verzichtet wurde.
Benutzeravatar
Klip
User
Beiträge: 98
Registriert: Donnerstag 10. August 2006, 20:39

fredistdurstig hat geschrieben: Der große Vorteil dieser kurzen und einfachen Schreibweise ist der, dass der Programmierer nicht aus Faulheit auf die Verwendung von Konstanten verzichtet - wie es in Java der Fall sein kann. Schließlich muss an jede Variable ZUSÄTZLICH noch das Wort "final" rangeschrieben werden.
Also wer schreibfaul ist, ist bei Java an der ganz falschen Adresse oO

Dazu kommt: Zwischen final und val sind 2 Zeichen Unterschied, wobei man bei Java sowieso fließend die Autovervollständigung der IDE nutzt.
lunar

@fredistdurstig: Funktionaler Stil ist in Python eine Frage des Geschmacks. Manches lässt sich funktional sehr schön lösen, anderes dagegen ist eher umständlich. In jedem Fall ist Python nun mal keine funktionale, sondern eine imperative Sprache, die Annahme, man müsse funktionalen Stil fördern, daher nicht richtig.

Dazumal ist Python eine dynamische Sprache, die noch dazu Konvention über Regeln stellt. Deswegen gibt es keinen harten Zugriffsschutz, sondern nur Unterstriche, und deswegen gibt es keine Konstanten. Das ist nicht „pythonisch“.

Davon abgesehen, wenn Du einen Wert nicht ändern möchtest, dann hindert Dich auch nichts daran, es nicht zu tun :) Du bist der Programmierer.

Im Übrigen würde ich gerne wissen, was Dich zur Annahme verleitet, die Implementierung von Konstanten brächte keinen zusätzlichen Aufwand. In Anbetracht des dynamischen Laufzeitmodells ist das nämlich ziemlicher Blödsinn. Man müsste wahrscheinlich durchaus viel Aufwand treiben, um Namensräume mit unveränderlichen Elementen auszustatten, mehr als es den Nutzen wert wäre.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

fredistdurstig hat geschrieben:Anscheinend ist funktionales Programmieren in Python kein großes Thema?
Nicht so sehr wie in Scala, aber die viele der aktivsten Poster hier im Forum gehören zum funktionalen Mob von daher würde ich sagen generell eher nicht, hier im kleinen ist funktionale Programmierung in Python durchaus populär.

(Die entsprechenden Smileys sind an den entsprechenden Stellen zu plazieren und werden als Übungsaufgabe dem Leser überlassen)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@Leonidas: Funktionaler Mob ist witzig. Überlege mir das auf ein T-Shirt zu drucken. Ist noch besser als "Pythopat", weil unverständlicher und "nerdiger". :-)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

BlackJack hat geschrieben:Funktionaler Mob ist witzig. Überlege mir das auf ein T-Shirt zu drucken.
Hmm, eigentlich eine coole Idee, also wenn da jemand Designvorschläge hat... ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

Also vielleicht hilfts...

in Perl sind Konstanten intern nix anderes als sogenannte "inline subs" sprich Prozeduren die nur einen konstaten Wert zurückgeben, weswegen vom Compiler der Aufruf wegoptimiert wird und direkt der Wert in den Bytecode kommt.

Perl verlangt auch keine Klammern um Funktionen auszuwerten.

Code: Alles auswählen

>>> def CONST():
...  return 4
... 
>>> CONST()
4
>>> CONST()=5
  File "<stdin>", line 1
SyntaxError: can't assign to function call
vielleicht bekommt ihrs auf der Grundlage ja "hübsch" hin... wenn die Klammern nicht stören sollte es ein Workaround sein.

PS: natürlich kann Ruby Konstanten ist ja nur ein Perldialekt mit Smalltalk OO! xD

UPDATE: Ok vergesst es in python könnte man ja jederzeit versehentlich die () vergessen und sowas wie

Code: Alles auswählen

CONST=5 
schreiben...
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

fredistdurstig hat geschrieben:Das man Konstanten in Python "nachprogrammieren" kann war mir schon klar. Mich wundert nur, dass das so nicht in der Sprache vorhanden ist, da es ja keinen weiteren Aufwand bedeutet hätte. Daher muss es ja auch einen ganz konkreten Grund geben, warum auf Konstanten ganz explizit verzichtet wurde.
Wie sma schon erklärt hat hätte es eben doch einen zusätzlichen Aufwand bedeutet, da das Laufzeitmodell auf Veränderungen ausgelegt ist. Jede Konstante müsste also zur Laufzeit extra forciert werden oder das Objektmodell müsste zweigeteilt werden(konstante Objekte vs. normale Objekte). Es reicht ja nicht einfach eine Variable read-only zu machen. Man muss ja auch sicherstellen, dass das Objekt selbst nicht verändert werden kann. Sonst hat man trotzdem Seiteneffekte. Was bei Ruby-„Konstanten“ übrigens nicht der Fall ist.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mein Rant bzgl. Typdeklarationen bezog sich nicht (nur) auf "final" sondern allgemein auf Dinge wie `private static final Map<String, List<Person>> f = new HashMap<String, List<Person>>(42);`. Des weiteren möchte ich klarstellen, dass es nicht so sehr um das Schreiben, wie denn um das Lesen geht. Überall in den Java-Code ein "final" gesprenkelt zu bekommen, macht das Zeug nicht lesbarer.

Ich glaube, dem funktionalen Aussage wurde nicht widersprochen, weil er von vielen geteilt wird. Wir ticken hier ja meist so, dass kein Widerspruch Zustimmung bedeutet und diese selten explizit gemacht wird, obwohl wahrscheinlich die meisten schon auch nach positivem Feedback gieren.

Python ist IMHO einfach sehr pragmatisch, was diese Idee, ich muss von Programmierer vor sich selbst (und seinen Kollegen) schützen angeht. Unbestritten kann es praktisch sein, gewissen Konventionen von einem Werkzeug erzwingen zu wollen, aber der Python-Interpreter kann das nun einmal nicht leisten und so muss man sich eben selbst an die Regeln halten. Man kann dennoch auf die selbe Art und Weise programmieren - man wird nur nicht gezwungen.

Wenn ich deine Variablen nun mal nicht als Konstanten respektiere (und hoffentlich einen guten Grund habe), dann kann ich sie doch ändern.

Stefan
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

sma hat geschrieben:Wenn ich deine Variablen nun mal nicht als Konstanten respektiere (und hoffentlich einen guten Grund habe), dann kann ich sie doch ändern.
Theoretisch ja, praktisch wundert man sich mit was für DAUs (ähm User=Programmer) man es in größeren Projekten zu tun bekommt.

Die Möglichkeit eine Variable explizit als read-only zu setzen erspart einiges an nerven, die man bräuchte um eine Konvention wie "großgeschriebene Variablen sind Konstanten" durchzusetzen.

Sonst debugt man letztendlich ne Woche um rauszubekommen dass der neueste Billigeinkauf des Chefs "total unkonventionellen total produktiven Code" beigesteuert hat...
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

LanX hat geschrieben:Sonst debugt man letztendlich ne Woche um rauszubekommen dass der neueste Billigeinkauf des Chefs "total unkonventionellen total produktiven Code" beigesteuert hat...
Davor retten einen aber keine Konstanten oder sonstiger Bondage, sondern nur ein Briefing.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@LanX Wenn du ein soziales Problem hast hilft dir statische Typisierung auch nicht sonderlich, mal abgesehen davon dass die in Java auch unschön gelöst ist, Haskell macht dass besser.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

DasIch hat geschrieben:@LanX Wenn du ein soziales Problem hast hilft dir statische Typisierung auch nicht sonderlich, mal abgesehen davon dass die in Java auch unschön gelöst ist, Haskell macht dass besser.
Ja, Haskell verhindert solcherlei Billigeinkäufe, weil es keine Haskell-Programmierer im Discounter gibt :) Abgesehen davon stimme ich natürlich zu, das auch Konstanten nicht vor Inkompetenz schützen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
LanX
User
Beiträge: 92
Registriert: Samstag 20. Februar 2010, 12:46

cofi hat geschrieben:Davor retten einen aber keine Konstanten oder sonstiger Bondage, sondern nur ein Briefing.
DasIch hat geschrieben:Wenn du ein soziales Problem hast hilft dir statische Typisierung auch nicht sonderlich,
lach ... erzählt mal dem Kunden dass er oder sein neuer Interner ne Pfeife ist... da kann man laaaaange Briefen! :D

Ich möchte da keine Geschichten auspacken was die Banken um 2000 rum alles eingestellt haben...

wie auch immer python hat doch bestimmt eine Möglichkeit einen schreibenden Zugriff abzufangen "setattr" oder so (perl hätte es)... das dürfte bei dieser Qualität von Kollegen locker ausreichen um sie zu "bremsen" ;-)

(von statisch hab ich nix gesagt)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

LanX hat geschrieben: wie auch immer python hat doch bestimmt eine Möglichkeit einen schreibenden Zugriff abzufangen "setattr" oder so (perl hätte es)...
Da wären wohl properties der richtige Weg. Allerdings würde das "Abfangen" den Sinn davon doch verfälschen...
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Leztendlich hat man doch immer die Möglichkeit, den Wert zu verändern.

Und wenn ein Kunde den Code ändert, dann muss er auch mit den Konsequenzen rechnen.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

jbs hat geschrieben:Und wenn ein Kunde den Code ändert, dann muss er auch mit den Konsequenzen rechnen.
Er wird sich sogar Konsequenzen wünschen, wenn er am Code etwas ändert :)
Antworten