PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Private/public in Python


Kennung Eins
2023-04-20, 22:33:14
In Python gibt's ja kein "echtes" private in einem Attribut.. Aber zumindest wirft es die richtigen Fehler, wenn man es simuliert verwendet. Dachte ich.

Ich habe auf einem Rechner 3.7, 3.9 3.10 und. 3.11 installiert. Im VSCode war bisher immer 3.7 als Standard eingestellt, habe nur sporadisch mal auf die anderen Versionen gewechselt. Nun habe ich aber mal fest auf 3.11 eingestellt und dabei bemerkt, dass es 'private' nun gar nicht mehr zu geben scheint?


class Test:
def __init__(self):
self.__a = "xyz"

t = Test()
t.__a = "abc"
print(t.__a)

Das hat früher (3.7) nen Fehler geschmissen, jetzt jedoch nicht mehr.

Warum?

pest
2023-04-21, 06:13:25
Das ist kein Sprachfeature und hat nix mit deiner Pythonversion zu tun
es ist nur eine Konvention - die Konvention würde auch jeder halbwegs brauchbare Linter bemeckern weil da leading underscores nicht vorgesehen sind
hier geht es auch eher um name-clashing bei potentiellem override

VSCode hat allerdings eine Option das anzumeckern


Press CTRL+SHIFT+P, type "Configure Language Specific Settings" and select Python. In JSON object add the following property:

"python.analysis.diagnosticSeverityOverrides": {
"reportPrivateUsage": "error"
}

Kennung Eins
2023-04-21, 08:49:33
Ok, deine Antwort hat mich verwirrt daher habe ich noch mal getestet - und jetzt bin ich maximal verwirrt.


class test:
def __init__(self):
self.__a = "privater Text"
def print(self):
print(self.__a)

t1 = test()
t1.print()
t1.__a = "abc"
print(t1.__a) #1
t1.print() #2



Eigentlich sollte doch bei #1 und bei #2 das gleiche Ergebnis geprintet werden. Wird es aber nicht.
Warum?

pest
2023-04-21, 09:00:00
Du erinnerst mich an meine Teammember, den muss ich auch immer was vorgoogeln :tongue:

https://peps.python.org/pep-0008/


Use the function naming rules: lowercase with words separated by underscores as necessary to improve readability.

Use one leading underscore only for non-public methods and instance variables.

To avoid name clashes with subclasses, use two leading underscores to invoke Python’s name mangling rules.

Python mangles these names with the class name: if class Foo has an attribute named __a, it cannot be accessed by Foo.__a. (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

Note: there is some controversy about the use of __names (see below).


was bedeutet das:
die Klassenvariable "__a" hat intern den Namen "_test__a"
die Zuweißung außerhalb des Klassendefinitionsscopes überschreibt diese Variable nicht!

Kennung Eins
2023-04-21, 14:09:00
Ok danke, das hat mich wieder auf Spur gebracht. Das mit den internen Namen wusste ich zwar - jedoch war mir nicht mehr klar, dass es keinen Fehler produziert, wenn ich "von außen" in __Variable schreibe. (Denn die interne Variable im Klassen-Scope ist nicht die Variable, die ich da außen quasi neu erzeugt habe)


class Test:
def __init__(self):
self.__a = input("Vorname: ")
self.__b = input("Name: ")
def print(self):
print(self.__a)

t1 = Test()
t1.print()
t1.__a = 5
print(t1.__a)
t1.print()
t1.__a = t1.__b # diesen Fehler wollte ich eigentlich produzieren, bzw daran hatte ich mich erinnert; dafür war mein Beispiel aber ungeeignet.


Über t1.__a erreiche ich nicht den internen Bezeichner _test__a

Danke!

pest
2023-04-21, 14:34:11
Das nennt sich duck-typing

Du kannst jede Klasseninstanz mit Features versehen. Hier hast du eine neue Membervariable "__a" hinzugefügt. Das können aber auch Funktionen etc sein.