Laut meinen Infos ist der tatsächliche Konstruktor einer Klasse nicht für mich zugänglich. __init__ ist kein ctor.
Mit C++ habe ich den ctor private gemacht, um zu verhindern, dass von der Klasse Instanzen erzeugt werden können bzw. damit nur die Klasse selbst sich instanziieren kann (Factory).
Geht das auch mit Python?
Ich möchte verhindern, dass irgendjemand von Außen eine Instanz davon erzeugen kann.
Oder könnte man dafür sorgen, dass nur eine Instanz der Klasse existiert und keine zweite erzeugt werden kann?
Insanziierung einer Klasse verhindern?
@MoonKid: Du erzeugst einfach nur ein Exemplar und beginnst den Klassennamen mit einem Unterstrich damit der Leser weiss dass das keine Name ist den er benutzen sollte. Ich habe so ein bisschen das Gefühl das Python nicht für Dich ist.
Der einfachste Ansatz sieht sicher so aus.MoonKid hat geschrieben:Ich möchte verhindern, dass irgendjemand von Außen eine Instanz davon erzeugen kann.
Code: Alles auswählen
class Foobar(object):
def __new__(cls):
raise NotImplementedError('Don\'t instantiate this class')
Wenn es dir im Endeffekt nur darum geht ein Singleton zu haben, dann gibt es dafür eigentlich eine relativ einfache Lösung. Im Netz findest du durchaus Singleton-Implementierungen für Python oder mit dem Borg-Pattern die Python-Version davon. Ich finde das akademisch ganz nett, aber es versucht im Endeffekt Python das mit Gewalt aufzuzwingen, wofür Python nicht gebaut ist und was Python gar nicht haben will. Langer Rede kurzer Sinn: Pack die Daten einfach in ein Modul, das ist bereits ein Singleton. Punkt.
@MoonKid: so etwas wie "privat" gibt es in Python nicht. Das erlaubt einem, neben den offiziellen Wegen auch inoffizielle Wege zu gehen. Es mußt nur klar sein, was der offizielle Weg ist, und das kannst Du ganz einfach in der Dokumentation tun. So in einem roten Kästchen: "Don't instantiate this class directly. Use function xy instead."
Kannst du das belegen? Nutze noch nicht lange Python, aber kenne Klassen-member, welche mit doppelten Unterstrich beginnen. Die sind meines Wissens "private".Sirius3 hat geschrieben:so etwas wie "privat" gibt es in Python nicht
Mit der Modullösung kann ich gut leben...
Es gibt nur private per Konvention. Dies sind Attribute, welche mit einem Unterstrich beginnen. Doppelte, führende Unterstriche werden im Bezug der Mehrfachvererbung (so gut wie nie) benötigt.
Wenn Du ein Buch/Tutorial verwendest, welche so private Attribute tituliert, nimm ein anderes
Wenn meine Klassen nicht direkt erzeugt werden sollen, verwende ich einen führenden Unterstrich beim Klassennamen und eine freie Funktion, um eine Instanz zu erzeugen.
Wenn Du ein Buch/Tutorial verwendest, welche so private Attribute tituliert, nimm ein anderes
Wenn meine Klassen nicht direkt erzeugt werden sollen, verwende ich einen führenden Unterstrich beim Klassennamen und eine freie Funktion, um eine Instanz zu erzeugen.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
Was du beschreibst sind protected-member. private/protected/public sind feststehende und von der Prog-Sprache unabhängige Begriffe der OOP.bwbg hat geschrieben:Es gibt nur private per Konvention. Dies sind Attribute, welche mit einem Unterstrich beginnen. Doppelte, führende Unterstriche werden im Bezug der Mehrfachvererbung (so gut wie nie) benötigt.
Mir ist klar, das einiges "lockerer" gesehen wird bei Python, aber die Unterscheidung sollte schon sein.
"per Konvention"?
http://www.python-kurs.eu/python3_klassen.php
Nein, bwbg hat das schon ganz richtig beschrieben. Einfacher führender Unterstrich für private Methoden, doppelter führender Unterstrich zur Vermeidung von Namenskollisionen.MoonKid hat geschrieben:Was du beschreibst sind protected-member. private/protected/public sind feststehende und von der Prog-Sprache unabhängige Begriffe der OOP.
Mir ist klar, das einiges "lockerer" gesehen wird bei Python, aber die Unterscheidung sollte schon sein.
Ja, per Konvention.MoonKid hat geschrieben:"per Konvention"?
Gut, damit wäre dann auch bestätigt, dass du ein schlechtes Tutorial verwendest. Vielleicht hättest du einfach mal das offizielle verwenden sollen:MoonKid hat geschrieben:http://www.python-kurs.eu/python3_klassen.php
https://docs.python.org/2/tutorial/classes.html#tut-private hat geschrieben:“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.
Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
Das Leben ist wie ein Tennisball.
@MoonKid: So ganz unabhängig sind die Begriffe nicht, denn man muss die ja im Kontext der jeweiligen Programmiersprache irgendwie abbilden. Insofern hat Python tatsächlich kein `private` oder `protected` denn alle Attribute sind technisch gesehen `public`, denn man kommt an alle heran. An die mit einem führenden Unterstrich, die halt nur per Konvention ”private” sind, und an die mit zwei führenden Unterstrichen kommt man auch heran, denn das „name mangeling” ist nicht als Zugriffsschutz gedacht, sondern um bei Mehrfachvererbung Namenskollisionen zu vermeiden in dem der Klassenname mit in den Attributnamen eingebaut wird:
Man kommt da also problemlos dran.
Code: Alles auswählen
class A(object):
def __init__(self, value=42):
self.__not_private = value
def __repr__(self):
return '{0.__class__.__name__}({1!r})'.format(self, self.__not_private)
def main():
a = A()
print(a)
a._A__not_private = 23
print(a)
Um das mal nachschlagbar zu machen
https://docs.python.org/3/tutorial/clas ... -variables
https://docs.python.org/3/tutorial/clas ... -variables