Warum gibt es in Python keine expliziten Zugriffsmodifikatoren?

28

Wenn "explizit ist besser als implizit", warum gibt es in Python keine expliziten Zugriffsmodifikatoren: öffentlich, geschützt, privat usw.?

Ich weiß, dass die Idee ist, dass der Programmierer durch einen Hinweis wissen sollte, was zu tun ist - keine Notwendigkeit, "rohe Gewalt" anzuwenden. Aber IMO 'Encapsulation' oder 'Information Hiding' soll nicht nur Menschen fernhalten, sondern ist auch eine Frage der Organisation und Struktur: Ihre Entwicklungsebenen sollten selbstdefinierende, klar abgegrenzte Bereiche und Grenzen haben, genau wie physische Systeme.

Kann mir hier bitte jemand mit einer soliden Erklärung helfen, warum Zugriffsbeschränkungen in Python, einer Sprache, die ansonsten nahezu perfekt zu sein scheint, eher impliziert als explizit sind?

Bearbeiten: Bisher habe ich 3 vorgeschlagene Antworten gesehen und festgestellt, dass meine Frage aus 2 Teilen besteht:

  1. Warum gibt es zum Beispiel keine Schlüsselwörter?

    private def myFunc(): 
        dostuff....

    statt IMO die hässlichen und schwer zu tippenden Unterstriche. Aber das ist nicht der wichtige Punkt.

  2. Wichtiger:

    Warum werden diese Zugriffsmodifikatoren nur "Empfehlungen" oder Hinweise und nicht erzwungen. Es wird schwer sein, später zu ändern? Es ist sehr einfach, "geschützt" in "öffentlich" zu ändern - und wenn Sie eine komplizierte Vererbungskette haben, die es schwierig macht, haben Sie ein schlechtes Design - Ihr Design sollte verfeinert werden, anstatt sich auf eine Sprachfunktion zu verlassen, die das Schreiben erleichtert schlecht strukturierter Code.

    Wenn Zugriffsmodifikatoren erzwungen werden, wird Ihr Code automatisch unterteilt. Sie wissen, dass bestimmte Segmente außerhalb des Gültigkeitsbereichs liegen, sodass Sie sich nur dann mit ihnen befassen müssen, wenn dies erforderlich ist. Und wenn Ihr Design nicht gut ist und Sie ständig Dinge in verschiedene Bereiche verschieben oder aus diesen entfernen, kann Ihnen die Sprache dabei helfen, Ihren Akt zu bereinigen.

So sehr ich Python liebe, finde ich, dass dieser zweite Punkt ein schwerwiegender Mangel ist. Und ich habe noch keine gute Antwort darauf.

Vektor
quelle
Mögliches Duplikat von Access-Spezifizierern in Python: ..., das als nicht konstruktiv eingestuft wurde.
Frank Shearar
2
@Frank Dies ist eine erneute Frage an diese Frage, um zu versuchen, konstruktiver zu sein. Ich habe die ursprüngliche Frage gelöscht.
@ Mark Trapp: Ah OK. Danke für die Klarstellung. Ich kann nicht sehen, wie ich meine Abstimmung zum Abschluss widerrufen kann.
Frank Shearar
@Frank Es wird von selbst altern.
Adam Lear
Das Problem dabei private def whateverist, dass dies class x: def whatever(self): passeine Abkürzung ist class x: pass; x.whatever = lambda self: pass, weshalb Sie im Grunde genommen einen privaten Modifikator für die Zuweisung benötigen würden
keppla

Antworten:

22

"Explizit ist besser als implizit" ist nur eine der Maximen in Pythons Designphilosophie. "Einfach ist besser als komplex" gibt es auch. Und obwohl es nicht im Zen von Python steht, ist "Wir stimmen alle Erwachsenen hier zu" eine andere.

Diese zweite Regel ist hier vielleicht die wichtigste. Wenn ich eine Klasse entwerfe, habe ich eine Vorstellung davon, wie sie verwendet werden soll. Aber ich kann unmöglich alle möglichen Verwendungen vorhersagen. Es kann sein, dass eine zukünftige Verwendung meines Codes den Zugriff auf die Variablen erfordert, die ich als privat angesehen habe. Warum sollte ich es mir schwer machen - oder sogar unmöglich - darauf zuzugreifen, wenn ein zukünftiger Programmierer (oder sogar ein zukünftiges Ich) sie benötigt? Am besten kennzeichnen Sie sie mit einer Warnung - wie Joonas bemerkt, ist ein einzelner Unterstrich das Standardpräfix -, dass sie intern sind und sich möglicherweise ändern. es erscheint jedoch unnötig, den Zugang insgesamt zu verbieten.

Daniel Roseman
quelle
1
"Einfach ist besser als komplex" und "Wir stimmen hier allen Erwachsenen zu" sind der Grund, warum Smalltalk keine Zugriffsmodifikatoren hat. Das Einfügen einer Methode in die Kategorie "privat" ist ein Hinweis, den Sie dreimal überlegen sollten, bevor Sie sie verwenden, und nicht mehr.
Frank Shearar
@Frank: "Das Einfügen einer Methode in die Kategorie" privat "ist ein Hinweis darauf, dass Sie dreimal nachdenken sollten, bevor Sie sie verwenden, und nicht mehr." Für mich bedeutet dies einfach, dass ich mir keine Sorgen machen muss, wenn ich mich nicht damit befasse damit.
Vector
8
Es gibt einen guten Grund, den Zugriff auf private Mitglieder zu verbieten: Dies kann zu einem Bruch der Klasseninvarianten führen. Wenn Sie keine privaten Mitglieder schreiben können, können Sie nicht sicher sein, ob sich Ihre Klasse richtig verhält.
SVICK
7
"Warum sollte ich es mir schwer machen - oder sogar unmöglich - darauf zuzugreifen, wenn ein zukünftiger Programmierer (oder sogar ein zukünftiges Ich) sie benötigt?" Denn eines der Grundprinzipien des Designs ist die Trennung zwischen der Schnittstelle (was ein Code bietet) und der Implementierung (wie er es bietet). Die Kapselung dient dazu, die Komplexität des Codes zu verringern, indem die Abhängigkeiten zwischen verschiedenen Teilen des Codes verringert werden. Daher werden public und private genau zum Zwecke der Vereinfachung des Codes verwendet, indem nur die Informationen angezeigt werden, die benötigt werden.
Giorgio
3
Kann nicht mehr zustimmen. Zugriffsmodifikatoren fördern zwei der wahrscheinlich am besten verstandenen Konzepte, um die Komplexität in großer Software zu verringern: Kapselung und Trennung von Bedenken. Wenn Sie keinen der beiden Server nicht bedienen, ist Python weder eine gute OOP-Sprache noch zum Erstellen großer Software geeignet, und daran ist nichts auszusetzen. Aber begründen Sie das Fehlen solcher Funktionen mit typischen hobbyistischen Argumenten wie "Warum Komplexität hinzufügen, wenn es nicht benötigt wird?" ist einfach falsch.
Daniel Shin
10

Ich würde vermuten, dass der Hauptgrund für die fehlenden Zugriffsmodifikatoren die Einfachheit ist

Wie Sie sagen, es geht nicht darum, Menschen fernzuhalten, sondern um Organisation. Der Hauptaspekt von "privat" ist, dass es eine Nachricht an die Benutzer Ihrer API sendet. Schreiben Sie bitte keinen Code, der davon abhängt.

Es ist trivial zu sagen, dass _x oder __x nicht außerhalb der Klasse verwendet werden sollten, aber in Pythons dynamischem Objektmodell ist es schwierig, überhaupt eine Notation zu finden.

class ActiveRow(object):
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

Wie kann man die Zugänglichkeit feststellen?

Ich denke, das war ein Kompromiss. Wenn Sie strikt nicht damit leben können, würde ich Ruby vorschlagen, das eine ähnliche Abstraktion und Dynamik aufweist, aber ein Objektmodell, das Zugriffsmodifikationen ermöglicht.

keppla
quelle
8
Ich denke das ist richtig, aber IMO, es ist schrecklich. Für eine Sprache, die Eleganz und Lesbarkeit als Verkaufsargument nutzt, ist das Schreiben __Methode__ ziemlich abscheulich und stumpf.
jiggy
2
Das ist nicht die Konvention, sondern __x__„magisch“ (dh Methoden, die aufgerufen werden, um die Sprachintegration zu ermöglichen, z. B. Überladen von Operatoren, Iterierbarkeit usw.). Die Konvention ist _x.
Keppla
6
Tut mir leid, ich habe immer noch Python im Kopf. Ich versuche so sehr, es zu mögen, aber solche Sachen sind ein bisschen verrückt. Vor allem jetzt, wo ich mir merken muss, wie viele Unterstriche eine Methode hat. Aus Sicht von OP scheinen explizite Modifikatoren klarer zu sein. Präzision ist großartig, aber Klarheit kann sie nicht übertreffen. Sie investieren 10-mal mehr in die Pflege von Code als in die Erstellung.
jiggy
2
Mein Beispiel sollte nicht unterschiedliche Unterstriche anzeigen, die Verwendung __init__war zufällig. In diesem Beispiel werden einige Eigenschaften des Objekts festgelegt, die zum Zeitpunkt der Kompilierung nicht bekannt sind, sodass ein expliziter Zugriffsmodifikator nicht hilfreich ist.
keppla
5
@jiggy: "Ich versuche so sehr, es zu mögen". Ich habe es 2 Jahre lang versucht - dann aufgegeben. :-( Scheint eine Skriptsprache zu sein, die gehackt wurde, um sich wie eine echte OOP-Sprache zu verhalten. Ich kann mir nicht vorstellen, eine große, komplexe App in Python zu schreiben, die gut gestaltet und lesbar ist Code zu pflegen als ihn zu bauen. “Einfache OOP- und typsichere Konzepte erfordern verrückte Hacks und Workarounds.
Vector
8

Die Python-Konvention sieht die Verwendung eines Unterstrich-Präfixes für geschützte / private Mitglieder vor.

Wenn diese Konvention befolgt wird, ist sie praktisch mit den Zugriffsmodifikatoren identisch, mit der Ausnahme, dass 1) Sie direkt am Namen des Mitglieds erkennen, ob er öffentlich ist oder nicht, und 2) Sie die "Kapselung" aufheben können , wenn Sie dies wirklich möchten (dies kann gerechtfertigt sein) in zB testing; in einigen anderen sprachen müssten sie reflection == more code verwenden).

Letztendlich ist es eine Frage des Geschmacks, aber wenn Sie dasselbe (mit etwas mehr Flexibilität) ohne spezielle Schlüsselwörter tun können, wird die Sprache kleiner und der Code wird prägnanter, was im Allgemeinen eine gute Sache ist.

Joonas Pulakka
quelle
2
"Wenn Sie dasselbe (mit etwas mehr Flexibilität) ohne spezielle Schlüsselwörter tun können, wird die Sprache kleiner und der Code wird prägnanter." Meiner Meinung nach ist dies im Allgemeinen nicht der Fall. (Auch wenn es mit dem Sonderfall der Zugriffsmodifikatoren wahr sein kann)
BenjaminB