Ich komme aus der Java-Welt und lese Bruce Eckels ' Python 3-Muster, Rezepte und Redewendungen .
Beim Lesen über Klassen heißt es weiter, dass in Python keine Instanzvariablen deklariert werden müssen. Sie verwenden sie einfach im Konstruktor und boom, sie sind da.
Also zum Beispiel:
class Simple:
def __init__(self, s):
print("inside the simple constructor")
self.s = s
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':', self.show())
Wenn das stimmt, kann jedes Objekt der Klasse Simple
einfach den Wert der Variablen s
außerhalb der Klasse ändern .
Zum Beispiel:
if __name__ == "__main__":
x = Simple("constructor argument")
x.s = "test15" # this changes the value
x.show()
x.showMsg("A message")
In Java wurden uns öffentliche / private / geschützte Variablen beigebracht. Diese Schlüsselwörter sind sinnvoll, da Sie manchmal Variablen in einer Klasse möchten, auf die niemand außerhalb der Klasse Zugriff hat.
Warum ist das in Python nicht erforderlich?
Antworten:
Es ist kulturell. In Python schreiben Sie nicht in die Instanz oder Klassenvariablen anderer Klassen. In Java hindert Sie nichts daran, dasselbe zu tun, wenn Sie es wirklich wollen - schließlich können Sie immer die Quelle der Klasse selbst bearbeiten, um den gleichen Effekt zu erzielen. Python lässt diesen Sicherheitsvorwand fallen und ermutigt Programmierer, verantwortlich zu sein. In der Praxis funktioniert das sehr gut.
Wenn Sie aus irgendeinem Grund private Variablen emulieren möchten, können Sie immer das
__
Präfix aus PEP 8 verwenden . Python zerlegt die Namen von Variablen__foo
so, dass sie für Code außerhalb der Klasse, die sie enthält, nicht leicht sichtbar sind (obwohl Sie sie umgehen können , wenn Sie entschlossen genug sind, genauso wie Sie Javas Schutz umgehen können , wenn Sie daran arbeiten ).Nach der gleichen Konvention
_
bedeutet das Präfix, dass Sie sich fernhalten, auch wenn Sie technisch nicht daran gehindert sind . Sie spielen nicht mit den Variablen einer anderen Klasse herum, die wie__foo
oder aussehen_bar
.quelle
Private Variablen in Python sind mehr oder weniger ein Hack: Der Interpreter benennt die Variable absichtlich um.
Wenn Sie nun versuchen,
__var
außerhalb der Klassendefinition zuzugreifen , schlägt dies fehl:Aber Sie können leicht damit durchkommen:
Sie wissen wahrscheinlich, dass Methoden in OOP folgendermaßen aufgerufen werden:
x.printVar() => A.printVar(x)
WennA.printVar()
auf ein Feld inx
zugegriffen werden kann , kann auf dieses Feld auch außerhalb zugegriffen werden.A.printVar()
Schließlich werden Funktionen für die Wiederverwendbarkeit erstellt. Den darin enthaltenen Anweisungen wird keine besondere Befugnis verliehen.Das Spiel ist anders, wenn ein Compiler beteiligt ist ( Datenschutz ist ein Konzept auf Compilerebene ). Es kennt die Klassendefinition mit Zugriffssteuerungsmodifikatoren, sodass Fehler auftreten können, wenn die Regeln zur Kompilierungszeit nicht befolgt werden
quelle
Wie in vielen der obigen Kommentare richtig erwähnt, vergessen wir nicht das Hauptziel von Access Modifiers: Benutzern von Code zu helfen, zu verstehen, was sich ändern soll und was nicht. Wenn Sie ein privates Feld sehen, spielen Sie nicht damit herum. Es handelt sich also hauptsächlich um syntaktischen Zucker, der in Python durch _ und __ leicht erreicht werden kann.
quelle
Es gibt eine Variation von privaten Variablen in der Unterstrichkonvention.
Es gibt einige subtile Unterschiede, aber um die ideologische Reinheit des Programmiermusters zu gewährleisten, ist es gut genug.
Es gibt Beispiele für @ private Dekorateure, die das Konzept genauer umsetzen, aber YMMV. Man könnte wohl auch eine Klassendefinition schreiben, die Meta verwendet
quelle
__x
Da eine Variable innerhalb der KlasseA
vom Compiler tatsächlich umgeschrieben wird_A__x
, ist sie immer noch nicht vollständig privat und kann weiterhin aufgerufen werden._A__x
, werde ich sie natürlich nicht berühren. Es könnte ansteckend sein. Ich werde verdammt noch mal davonlaufen."In Java wurden uns öffentliche / private / geschützte Variablen beigebracht."
"Warum ist das in Python nicht erforderlich?"
Aus dem gleichen Grund ist es in Java nicht erforderlich .
Sie sind frei zu verwenden - oder auch nicht verwenden ,
private
undprotected
.Als Python- und Java-Programmierer habe ich das gefunden
private
und binprotected
sehr, sehr wichtige Designkonzepte. Aber als eine praktische Angelegenheit, in Zehntausende von Zeilen Java und Python, ich habe nie wirklich verwendetprivate
oderprotected
.Warum nicht?
Hier ist meine Frage "Vor wem geschützt?"
Andere Programmierer in meinem Team? Sie haben die Quelle. Was bedeutet geschützt, wenn sie es ändern können?
Andere Programmierer in anderen Teams? Sie arbeiten für die gleiche Firma. Sie können - mit einem Telefonanruf - die Quelle erhalten.
Kunden? Es ist Work-for-Hire-Programmierung (im Allgemeinen). Die Clients besitzen (im Allgemeinen) den Code.
Also, vor wem - genau - schütze ich es?
quelle
Wie bereits erwähnt, können Sie angeben, dass eine Variable oder Methode privat ist, indem Sie einen Unterstrich voranstellen. Wenn Sie nicht der Meinung sind, dass dies ausreicht, können Sie jederzeit den
property
Dekorateur verwenden. Hier ist ein Beispiel:Auf diese Weise verweist jemand oder etwas, auf das verwiesen
bar
wird, tatsächlich auf den Rückgabewert derbar
Funktion und nicht auf die Variable selbst. Daher kann darauf zugegriffen, aber nicht geändert werden. Wenn jemand es wirklich wollte, konnte er es einfach verwenden_bar
und ihm einen neuen Wert zuweisen. Es gibt keine todsichere Möglichkeit, jemanden daran zu hindern, auf Variablen und Methoden zuzugreifen, die Sie verbergen möchten, wie wiederholt gesagt wurde. Jedoch mitproperty
ist jedoch die klarste Nachricht, die Sie senden können, dass eine Variable nicht bearbeitet werden soll.property
kann auch für komplexere Zugriffspfade für Getter / Setter / Deleter verwendet werden, wie hier erläutert: https://docs.python.org/3/library/functions.html#propertyquelle
Python unterstützt private Bezeichner nur eingeschränkt, da der Klassenname automatisch allen Bezeichnern vorangestellt wird, die mit zwei Unterstrichen beginnen. Dies ist für den Programmierer größtenteils transparent, aber der Nettoeffekt besteht darin, dass alle auf diese Weise benannten Variablen als private Variablen verwendet werden können.
Siehe hier .
Im Allgemeinen ist Pythons Implementierung der Objektorientierung im Vergleich zu anderen Sprachen etwas primitiv. Aber ich genieße das eigentlich. Es ist eine sehr konzeptionell einfache Implementierung und passt gut zum dynamischen Stil der Sprache.
quelle
Das einzige Mal, dass ich private Variablen verwende, ist, wenn ich beim Schreiben oder Lesen aus der Variablen andere Dinge tun muss und daher die Verwendung eines Setzers und / oder Getters erzwingen muss.
Auch dies geht, wie bereits erwähnt, an die Kultur. Ich habe an Projekten gearbeitet, in denen das Lesen und Schreiben anderer Klassenvariablen für alle kostenlos war. Als eine Implementierung veraltet war, dauerte es viel länger, alle Codepfade zu identifizieren, die diese Funktion verwendeten. Wenn die Verwendung von Setzern und Gettern erzwungen wurde, konnte leicht eine Debug-Anweisung geschrieben werden, um zu identifizieren, dass die veraltete Methode aufgerufen wurde und der Codepfad, der sie aufruft.
Wenn Sie sich in einem Projekt befinden, in dem jeder eine Erweiterung schreiben kann, ist es wichtig, Benutzer über veraltete Methoden zu informieren, die in einigen Releases verschwinden sollen, um den Modulbruch bei Upgrades so gering wie möglich zu halten.
Meine Antwort lautet also: Wenn Sie und Ihre Kollegen einen einfachen Codesatz verwalten, ist der Schutz von Klassenvariablen nicht immer erforderlich. Wenn Sie ein erweiterbares System schreiben, ist es unerlässlich, wenn Änderungen am Kern vorgenommen werden, die von allen Erweiterungen mithilfe des Codes erfasst werden müssen.
quelle
Sorry Leute, dass ihr den Thread "wiederbelebt" habt, aber ich hoffe, das wird jemandem helfen:
Wenn Sie in Python3 nur die Klassenattribute "kapseln" möchten, wie in Java, können Sie genau das Gleiche tun:
Um dies zu instanziieren, gehen Sie wie folgt vor:
Beachten Sie Folgendes:
print(ss.__s)
Gibt einen Fehler aus.In der Praxis verschleiert Python3 den globalen Attributnamen. Drehen Sie dies wie ein "privates" Attribut, wie in Java. Der Name des Attributs ist immer noch global, jedoch nicht zugänglich, wie ein privates Attribut in anderen Sprachen.
Aber hab keine Angst davor. Es spielt keine Rolle. Es macht auch den Job. ;)
quelle
private und geschützte Konzepte sind sehr wichtig. Aber Python - nur ein Werkzeug für das Prototyping und die schnelle Entwicklung mit begrenzten Ressourcen, die für die Entwicklung zur Verfügung stehen. Deshalb werden einige Schutzstufen in Python nicht so streng eingehalten. Sie können "__" in Klassenmitgliedern verwenden, es funktioniert ordnungsgemäß, sieht aber nicht gut genug aus - jeder Zugriff auf ein solches Feld enthält diese Zeichen.
Sie können auch feststellen, dass das Python-OOP-Konzept nicht perfekt ist, Smaltalk oder Ruby viel näher am reinen OOP-Konzept. Sogar C # oder Java sind näher.
Python ist ein sehr gutes Werkzeug. Aber es ist vereinfachte OOP-Sprache. Syntaktisch und konzeptionell vereinfacht. Das Hauptziel der Python-Existenz ist es, Entwicklern die Möglichkeit zu geben, sehr schnell leicht lesbaren Code mit hohem Abstraktionsgrad zu schreiben.
quelle
Python hat keine privaten Variablen wie C ++ oder Java. Auf Wunsch können Sie auch jederzeit auf jede Mitgliedsvariable zugreifen. In Python benötigen Sie jedoch keine privaten Variablen, da es in Python nicht schlecht ist, die Variablen Ihrer Klassenmitglieder verfügbar zu machen. Wenn Sie eine Mitgliedsvariable kapseln müssen, können Sie dies später mithilfe von "@property" tun, ohne den vorhandenen Clientcode zu beschädigen.
In Python wird der einzelne Unterstrich "_" verwendet, um anzuzeigen, dass eine Methode oder Variable nicht als Teil der öffentlichen API einer Klasse betrachtet wird und dass dieser Teil der API zwischen verschiedenen Versionen wechseln kann. Sie können diese Methoden / Variablen verwenden, aber Ihr Code könnte beschädigt werden, wenn Sie eine neuere Version dieser Klasse verwenden.
Der doppelte Unterstrich "__" bedeutet keine "private Variable". Sie verwenden es, um Variablen zu definieren, die "klassenlokal" sind und von Unterklassen nicht leicht überschrieben werden können. Der Name der Variablen wird entstellt.
Zum Beispiel:
self .__ foobars Name wird automatisch in self._A__foobar in Klasse A entstellt. In Klasse B wird er in self._B__foobar entstellt. So kann jede Unterklasse ihre eigene Variable __foobar definieren, ohne die übergeordneten Variablen zu überschreiben. Nichts hindert Sie jedoch daran, auf Variablen zuzugreifen, die mit doppelten Unterstrichen beginnen. Das Namens-Mangling verhindert jedoch, dass Sie diese Variablen / Methoden nebenbei aufrufen.
Ich empfehle dringend, Raymond Hettingers beim Reden über das "Pythons Class Development Toolkit" von Pycon 2013 (sollte auf Youtube verfügbar sein) zuzusehen. Dies ist ein gutes Beispiel dafür, warum und wie Sie @property- und "__" - Instanzvariablen verwenden sollten.
quelle
@property
Ding Teil von Standard-Python oder ist es spezifisch für eine IDE?property
integrierte Funktion zu verwenden, die seit Python 2.2C#
Mit diesem einfachen Trick können Sie einen Getter und Setter simulieren :Verwenden Sie es dann ähnlich wie in
C#
:Es wird lediglich eine statische lokale Variable in einer Funktion deklariert, die eine get / set-Rolle spielt, da dies die einzige Möglichkeit ist, eine Variable über get- und set-Methoden freizugeben, ohne sie für eine Klasse oder Datei global zu machen.
quelle