it-swarm.com.de

Definieren von privaten Modulfunktionen in Python

Gemäß http://www.faqs.org/docs/diveintopython/fileinfo_private.html :

Wie die meisten Sprachen hat Python die Konzept der privaten Elemente: 

  • Privatgelände Funktionen, die nicht von .__ aufgerufen werden können. außerhalb ihres Moduls

Wenn ich jedoch zwei Dateien definiere:

#a.py
__num=1

und:

#b.py
import a
print a.__num

wenn ich b.py starte, wird 1 ausgegeben, ohne eine Ausnahme zu machen. Ist Diveintopython falsch oder habe ich etwas falsch verstanden? Und gibt es eine Möglichkeit, definieren die Funktion eines Moduls als privat?

192
olamundo

In Python hängt "Privatsphäre" von der Zustimmung der Erwachsenen ab - Sie können es nicht erzwingen (genauso wenig wie Sie es im wirklichen Leben können ;-). Ein einzelner führender Unterstrich bedeutet, dass Sie nicht "von außen" darauf zugreifen dürfen - zwei führende Unterstriche (w/o nachfolgende Unterstriche) tragen die Botschaft noch stärker ... aber letztendlich kommt es immer noch auf soziale Konventionen und Konsens an: Pythons Selbstbeobachtung ist so stark, dass Sie keine Handschellen tragen können jeden anderen Programmierer auf der Welt, um Ihre Wünsche zu respektieren.

((Übrigens, obwohl es ein streng gehütetes Geheimnis ist, gilt dasselbe für C++: Bei den meisten Compilern reicht eine einfache #define private public -Zeile, bevor #include Ihre .h -Datei erstellt um deine "Privatsphäre" zu verunstalten ...! -))

284
Alex Martelli

Es kann Verwirrung zwischen Klassenprivaten und Modulprivaten geben.

Ein Modul privat beginnt mit one Unterstrich
Ein solches Element wird nicht mitkopiert, wenn Sie die from <module_name> import *-Form des Importbefehls verwenden. es wird jedoch importiert, wenn die import <moudule_name>-Syntax verwendet wird ( siehe Ben Wilhelms Antwort )
Entfernen Sie einfach einen Unterstrich aus dem a .__ num des Beispiels der Frage und er wird nicht in Modulen angezeigt, die a.py mit der from a import *-Syntax importieren.

Ein class private beginnt mit zwei Unterstrichen (aka dunder, d. H. D-ouble under-score) 
Eine solche Variable hat ihren Namen "entstellt", um den Klassennamen usw. aufzunehmen.
Es kann immer noch außerhalb der Klassenlogik über den verfälschten Namen zugegriffen werden.
Obwohl die Namensveränderung als milde Präventionseinrichtung gegen unbefugten Zugriff dienen kann, besteht ihr Hauptzweck darin, mögliche Namenskollisionen mit Klassenmitgliedern der Vorfahrklassen zu verhindern. Sehen Sie Alex Martellis lustigen, aber genauen Hinweis auf zustimmende Erwachsene, während er die Konvention beschreibt, die in Bezug auf diese Variablen verwendet wird.

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>
244
mjv

Diese Frage wurde nicht vollständig beantwortet, da der Datenschutz des Moduls nicht rein konventionell ist und da import den Datenschutz des Moduls je nach Verwendung des Moduls möglicherweise nicht erkennt.

Wenn Sie private Namen in einem Modul definieren, werden diese Namen wird in ein Skript importiert, das die Syntax 'import module_name' verwendet. Vorausgesetzt, Sie hatten in Ihrem Beispiel das Modul private, _num, in a.py richtig definiert, wie so ..

#a.py
_num=1

Sie könnten in b.py mit dem Modulnamensymbol darauf zugreifen:

#b.py
import a
...
foo = a._num # 1

Um nur Nicht-Privates aus a.py zu importieren, müssen Sie die Syntax from verwenden:

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

Aus Gründen der Übersichtlichkeit ist es jedoch besser, beim Import von Namen aus Modulen explizit zu sein, anstatt sie alle mit einem '*' zu importieren:

#b.py
from a import name1 
from a import name2
...
72
Ben Wilhelm

Python erlaubt private class - Mitglieder mit dem doppelten Unterstrich. Diese Technik funktioniert nicht auf Modulebene, daher denke ich, dass dies ein Fehler in Dive Into Python ist.

Hier ist ein Beispiel für private Klassenfunktionen:

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails
29
Andrew Hare

Sie können eine innere Funktion hinzufügen:

def public(self, args):
   def private(self.root, data):
       if (self.root != None):
          pass #do something with data

So etwas, wenn Sie dieses Maß an Privatsphäre wirklich benötigen.

5
Ilian Zapryanov

Dies ist eine uralte Frage, aber sowohl für private (eine Unterstreichung) als auch für Klassen-private (zwei Unterstriche) veränderte Variablen werden jetzt in der Standarddokumentation behandelt:

Das Python-Tutorial » Klassen » Private Variablen

1
user1338062

eingebettet mit Verschlüssen oder Funktionen ist eine Möglichkeit. Dies ist in JS üblich, obwohl es für Nicht-Browser-Plattformen oder Browser-Worker nicht erforderlich ist.

In Python scheint es ein bisschen seltsam zu sein, aber wenn etwas wirklich versteckt werden muss, könnte dies der Fall sein. Um mehr auf den Punkt zu bringen, wenn Sie die Python-API verwenden und Dinge, die in der C-Sprache (oder einer anderen Sprache) verborgen werden müssen, zu verwenden, ist wahrscheinlich der beste Weg. Andernfalls würde ich den Code in eine Funktion einfügen, aufrufen und die Elemente zurückgeben lassen, die Sie exportieren möchten.

0
Martian Fame