2016-07-28 22 views
1

Ich folge diesem link und versuche, eine Singleton-Klasse mit Metaclass zu machen. Aber ich möchte einige interne Verbesserungen an dieser Singleton-Klasse vornehmen und möchte, dass die Benutzer eine andere Klasse verwenden (nennen wir sie MySingleton(__Singleton)). Also habe ich beschlossen, es privat zu machen, aber es gibt den folgenden Fehler.Python: Klasse mit doppeltem Unterstrich

enter image description here

Mein einziger Zweck ist __Singleton zu verhindern, von außen verwendet werden. Wie kann ich das erreichen?

Auf eine separate Notiz, ist es eine gute Praxis, doppelte Unterstreichung mit Klassen zu verwenden?

+1

Sie möchten verhindern, dass '__Singleton' außerhalb dessen verwendet wird? –

+0

Außerhalb meines Moduls. Nur "MySingleton" sollte für jeden zugänglich sein, der dies nutzen möchte. –

+0

Führende doppelte Unterstriche sind kein universeller Datenschutzmarker. Sie machen die Dinge nicht privater als einzelne Unterstriche. – user2357112

Antwort

3

Innerhalb der Klasse erhält der Bezeichner __Singletonmangled. Am Ende haben Sie Probleme, weil Namensverfälschung nur innerhalb von Klassen (nicht außerhalb) auftritt. Also __Singleton als Klassenname bedeutet etwas anderes als __Singleton, wenn Sie in einer Klasse Suite sind.

Jede Kennung des Formulars __spam (zumindest zwei führenden Unterstrichen, höchstens einen nacheilenden Unterstrich) ist textlich mit _classname__spam ersetzt, wobei der aktuellen Klasse Klassenname ist der Name mit Unterstrich (en) gestrippt. Dieses Mangeln erfolgt ohne Berücksichtigung der syntaktischen Position des Bezeichners, solange es innerhalb der Definition einer Klasse auftritt.

Beachten Sie, dass der Hauptgrund für Mangeln ist, weil es

... hilfreich ist für die Vermietung Subklassen Methoden außer Kraft setzen, ohne Intramethodenaufrufe zu brechen.

auch:

... Namenskonflikte von Namen mit den Namen von Unterklassen definiert zu vermeiden

Als solche gibt es wirklich keinen Grund, eine Klasse mit führenden haben doppelte Unterstriche im Namen (es gibt keine Möglichkeit von intraclass Methodenaufrufen, die Konflikte mit Klassennamen haben). Ein einzelner Unterstrich ist ein gut genug Signal für die Nutzer, dass sie nicht diese Klasse verwenden sollten:

... einen Namen mit einem Unterstrich (zB _spam) Präfix sollte als nicht-öffentlichen Teil der behandelt werden API (ob es eine Funktion, eine Methode oder ein Datenelement ist). Es sollte als Implementierungsdetail betrachtet werden und kann ohne vorherige Ankündigung geändert werden.


ich es nicht raten würde, aber wenn Sie wirklich es arbeiten wollen, können Sie wahrscheinlich globals verwenden, um die Klasse zu nachschlagen:

class __Foo(object): 
    def __init__(self): 
     super(globals()['__Foo'], self).__init__() 

f = __Foo() 
print f 
+0

versucht Warum ist es nicht ratsam? –

+1

@PankajSinghal - Es ist eine Menge extra Eingabe und seltsame (etwas verwirrend und ineffizient) Introspektion für absolut keinen Gewinn ... – mgilson

1

Jeder Name innerhalb einer Klassendefinition mit zwei führenden Unterstrichen wird gemangelt, daher wird __Singleton zu _Singleton__Singleton. Um klarzustellen, dass eine Klasse nicht öffentlich verwendet werden soll, verwenden Sie einen Unterstrich.

+0

selbst '_Singleton__Singleton' funktioniert nicht. Probier es einfach mal aus –

+0

Hast du wirklich versucht 'class _Singleton__Singleton (type): ...'? – Daniel

+0

Nein, ich habe 'super (_Singleton__Singleton, cls)' –

1

Python nicht haben private variables; Sie sind alle von außen zugänglich.

"Private" Instanzvariablen, auf die nur innerhalb eines Objekts zugegriffen werden kann, sind in Python nicht vorhanden. Es gibt jedoch eine Konvention, der der meiste Python-Code folgt: Ein Name, dem ein Unterstrich vorangestellt ist (zB _spam), sollte als nichtöffentlicher Teil der API behandelt werden (unabhängig davon, ob es sich um eine Funktion, eine Methode oder ein Datenelement handelt). . Es sollte als Implementierungsdetail betrachtet und ohne Vorankündigung geändert werden.

Das Python-Kochbuch bietet eine Singleton class, die von anderen Klassen zu Singletons vererbt werden kann.