Python daje nam możliwość tworzenia „prywatny” metod i zmiennych w klasie przez poprzedzenie podwójne podkreślenia do nazwy, na przykład: __myPrivateMethod()
. Jak zatem to wyjaśnić
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
O co chodzi?!
Wytłumaczę to trochę tym, którzy tego nie rozumieją.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
To, co tam zrobiłem, to utworzenie klasy za pomocą metody publicznej i prywatnej oraz utworzenie jej instancji.
Następnie nazywam tę metodę publiczną.
>>> obj.myPublicMethod()
public method
Następnie próbuję wywołać jego prywatną metodę.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Tutaj wszystko wygląda dobrze; nie możemy tego nazwać. W rzeczywistości jest „prywatny”. Właściwie to nie jest. Uruchomienie dir () na obiekcie ujawnia nową magiczną metodę, którą Python tworzy magicznie dla wszystkich twoich „prywatnych” metod.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
Nazwa tej nowej metody jest zawsze znakiem podkreślenia, po której następuje nazwa klasy, a następnie nazwa metody.
>>> obj._MyClass__myPrivateMethod()
this is private!!
Tyle o enkapsulacji, co?
W każdym razie zawsze słyszałem, że Python nie obsługuje enkapsulacji, więc po co w ogóle próbować? Co daje?
Odpowiedzi:
Szyfrowanie nazw służy do tego, aby podklasy przypadkowo nie zastępowały prywatnych metod i atrybutów ich nadklas. Nie jest zaprojektowany, aby zapobiegać celowemu dostępowi z zewnątrz.
Na przykład:
Oczywiście psuje się, jeśli dwie różne klasy mają tę samą nazwę.
źródło
Przykład funkcji prywatnej
źródło
self = MyClass()
self.private_function()
. : D Oczywiście, że to nie działa w klasach, ale wystarczy zdefiniować niestandardową funkcję:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- jakie są te 1, 4 i 0 magicznych liczb?self = MyClass(); self.private_function()
i zawiedzie, gdy zostanie wywołane zax = self.private_function()
pomocą metody.Kiedy po raz pierwszy przyszedłem z Javy do Pythona, nienawidziłem tego. Przestraszyło mnie to na śmierć.
Dzisiaj może to być jedna rzecz, którą najbardziej lubię w Pythonie.
Uwielbiam być na platformie, na której ludzie sobie ufają i nie czują, że muszą budować nieprzeniknione ściany wokół swojego kodu. W silnie zamkniętych językach, jeśli interfejs API zawiera błąd, a ty zorientowałeś się, co poszło nie tak, nadal możesz nie być w stanie go obejść, ponieważ potrzebna metoda jest prywatna. W Pythonie postawa brzmi: „pewnie”. Jeśli uważasz, że rozumiesz sytuację, być może nawet ją przeczytałeś, to wszystko, co możemy powiedzieć, to „powodzenia!”.
Pamiętaj, że kapsułkowanie nie jest nawet słabo związane z „bezpieczeństwem” lub utrzymywaniem dzieci z dala od trawnika. To tylko kolejny wzorzec, który powinien być użyty, aby podstawa kodu była łatwiejsza do zrozumienia.
źródło
From http://www.faqs.org/docs/diveintopython/fileinfo_private.html
źródło
Często używanym zwrotem jest „wszyscy tutaj zgadzamy się na dorosłych”. Przygotowując pojedynczy znak podkreślenia (nie ujawniaj) lub podwójny znak podkreślenia (ukryj), mówisz użytkownikowi swojej klasy, że zamierzasz być w jakiś sposób „prywatny”. Jednak ufasz wszystkim, którzy zachowują się odpowiedzialnie i szanują to, chyba że mają ku temu ważny powód (np. Debuggery, uzupełnianie kodu).
Jeśli naprawdę musisz mieć coś prywatnego, możesz to zaimplementować w rozszerzeniu (np. W C dla CPython). Jednak w większości przypadków po prostu uczysz się Pythońskiego sposobu robienia rzeczy.
źródło
To nie tak, że absolutnie nie możesz ominąć prywatności członków w żadnym języku (arytmetyka wskaźników w C ++, Refleksje w .NET / Java).
Chodzi o to, że pojawia się błąd, jeśli przypadkowo wywołujesz metodę prywatną. Ale jeśli chcesz strzelić sobie w stopę, zrób to.
Edycja: Nie próbujesz zabezpieczyć swoich rzeczy za pomocą enkapsulacji OO, prawda?
źródło
The
class.__stuff
Konwencja nazewnictwa pozwala programista wie, że nie ma dostępu__stuff
z zewnątrz. Nazwa „mangling” sprawia, że jest mało prawdopodobne, że ktoś zrobi to przypadkowo.To prawda, że nadal możesz to obejść, jest to nawet łatwiejsze niż w innych językach (które BTW również pozwala ci to zrobić), ale żaden programista Python nie zrobiłby tego, jeśli zależy mu na enkapsulacji.
źródło
Podobne zachowanie występuje, gdy nazwy atrybutów modułów zaczynają się od pojedynczego podkreślenia (np. _Foo).
Atrybuty modułu nazwane jako takie nie zostaną skopiowane do modułu importującego podczas korzystania z
from*
metody, np .:Jest to jednak konwencja, a nie ograniczenie językowe. To nie są prywatne atrybuty; mogą być przywoływane i manipulowane przez dowolnego importera. Niektórzy twierdzą, że z tego powodu Python nie może zaimplementować prawdziwej enkapsulacji.
źródło
To tylko jedna z opcji wyboru języka. Na pewnym poziomie są uzasadnione. Robią to, więc musisz zrobić wszystko, co w twojej mocy, aby wywołać metodę, a jeśli naprawdę potrzebujesz jej tak bardzo, musisz mieć całkiem dobry powód!
Debugowanie haków i testowanie przychodzą na myśl jako możliwe aplikacje, oczywiście używane w sposób odpowiedzialny.
źródło
W Pythonie 3.4 jest to zachowanie:
https://docs.python.org/3/tutorial/classes.html#tut-private
Nawet jeśli pytanie jest stare, mam nadzieję, że mój fragment może być pomocny.
źródło
Najważniejszą kwestią związaną z prywatnymi metodami i atrybutami jest poinformowanie programistów, aby nie nazywali go poza klasą, a to jest hermetyzacja. można źle zrozumieć bezpieczeństwo wynikające z hermetyzacji. kiedy ktoś celowo używa takiej składni (poniżej), o której wspomniałeś, nie chcesz enkapsulacji.
Przeprowadziłem migrację z C # i na początku też było to dla mnie dziwne, ale po pewnym czasie doszedłem do wniosku, że tylko sposób, w jaki projektanci kodu Python myślą o OOP, jest inny.
źródło
Jak rozumiem, nie mogą być prywatni. Jak można egzekwować prywatność?
Oczywista odpowiedź brzmi: „członkowie prywatni są dostępni tylko przez
self
”, ale to nie zadziałałoby -self
nie jest to szczególne w Pythonie, jest niczym więcej niż powszechnie używaną nazwą pierwszego parametru funkcji.źródło