Python дает нам возможность создавать «частные» методы и переменные в классе, предваряя двойные подчеркивания к имени, например: __myPrivateMethod()
. Как же тогда это объяснить?
>>> 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!!
В чем дело?!
Я объясню это немного тем, кто не совсем понял.
>>> 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 () на объекте открывает новый магический метод, который python создает магическим образом для всех ваших «приватных» методов.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
Имя этого нового метода всегда является подчеркиванием, за которым следует имя класса, а затем имя метода.
>>> obj._MyClass__myPrivateMethod()
this is private!!
Так много для инкапсуляции, а?
В любом случае, я всегда слышал, что Python не поддерживает инкапсуляцию, так зачем даже пытаться? Что дает?
Ответы:
Скремблирование имен используется, чтобы гарантировать, что подклассы не переопределят случайно частные методы и атрибуты своих суперклассов. Он не предназначен для предотвращения преднамеренного доступа извне.
Например:
Конечно, он ломается, если два разных класса имеют одинаковые имена.
источник
Пример приватной функции
источник
self = MyClass()
self.private_function()
, : D Конечно, это не работает в классах, но вы просто должны определить пользовательскую функцию:def foo(self): self.private_function()
function_call.startswith('self.')
.inspect.stack()[1][4][0].strip()
<- что это за магические числа 1, 4 и 0?self = MyClass(); self.private_function()
и оно вызывает ошибку при вызовеx = self.private_function()
внутри метода.Когда я впервые пришел с Java на Python, я ненавидел это. Это напугало меня до смерти.
Сегодня это может быть одна вещь, которую я люблю больше всего в Python.
Мне нравится находиться на платформе, где люди доверяют друг другу и не чувствуют, что им нужно строить непроницаемые стены вокруг своего кода. В сильно инкапсулированных языках, если в API есть ошибка, и вы выяснили, что идет не так, вы все равно не сможете обойти ее, потому что необходимый метод является закрытым. В Python отношение: «конечно». Если вы думаете, что понимаете ситуацию, возможно, вы даже читали ее, тогда все, что мы можем сказать, - это «удачи!».
Помните, что инкапсуляция даже слабо не связана с «безопасностью» или с тем, чтобы дети не попадали на газон. Это просто еще один шаблон, который следует использовать, чтобы облегчить понимание кодовой базы.
источник
С http://www.faqs.org/docs/diveintopython/fileinfo_private.html
источник
Фраза, которая обычно используется, это «мы все взрослые по соглашению». Подставляя одно подчеркивание (не обнажая) или двойное подчеркивание (скрывая), вы говорите пользователю своего класса, что вы намерены каким-то образом сделать его «закрытым». Однако вы доверяете всем остальным вести себя ответственно и уважать это, если только у них нет веских причин не делать этого (например, отладчики, завершение кода).
Если вам действительно нужно что-то частное, то вы можете реализовать это в расширении (например, в C для CPython). В большинстве случаев, однако, вы просто изучаете Pythonic, как делать вещи.
источник
Это не значит, что вы абсолютно не можете обойти конфиденциальность членов на любом языке (арифметика указателей в C ++, Reflections в .NET / Java).
Дело в том, что вы получаете ошибку, если пытаетесь вызвать частный метод случайно. Но если вы хотите выстрелить себе в ногу, продолжайте и сделайте это.
Изменить: Вы не пытаетесь защитить свои вещи с помощью OO-инкапсуляции, не так ли?
источник
Соглашение
class.__stuff
об именах позволяет программисту знать, что он не предназначен для доступа__stuff
извне. Название искажает имя, поэтому вряд ли кто-нибудь сделает это случайно.Правда, вы все еще можете обойти это, это даже проще, чем в других языках (которые BTW также позволяет вам делать это), но ни один программист на Python не сделает этого, если он заботится об инкапсуляции.
источник
Подобное поведение существует, когда имена атрибутов модуля начинаются с одного подчеркивания (например, _foo).
Атрибуты модуля, названные как таковые, не будут скопированы в импортирующий модуль при использовании
from*
метода, например:Однако это соглашение, а не ограничение языка. Это не личные атрибуты; на них может ссылаться и манипулировать любой импортер. Некоторые утверждают, что из-за этого Python не может реализовать истинную инкапсуляцию.
источник
Это только один из тех вариантов выбора языка. На каком-то уровне они оправданы. Они делают это так, что вам нужно уйти довольно далеко, чтобы попытаться вызвать метод, и если вам это действительно нужно, у вас должна быть довольно веская причина!
В качестве возможных приложений приходят на ум отладки и тестирование, которые, конечно же, используются ответственно.
источник
В Python 3.4 это поведение:
https://docs.python.org/3/tutorial/classes.html#tut-private
Даже если вопрос старый, я надеюсь, что мой фрагмент может быть полезным.
источник
Самая важная забота о закрытых методах и атрибутах - это запретить разработчикам вызывать его вне класса, а это инкапсуляция. можно неправильно понять защиту от инкапсуляции. когда кто-то сознательно использует синтаксис, подобный тому, который вы упомянули ниже, вы не хотите инкапсуляции.
Я перешел с C #, и сначала это тоже было странно для меня, но через некоторое время я пришел к мысли, что только то, как дизайнеры кода Python думают об ООП, отличается.
источник
Насколько я понимаю, они не могут быть частными. Как обеспечить конфиденциальность?
Очевидный ответ: «Доступ к закрытым членам возможен только через
self
», но это не сработает -self
это не является особенным в Python, это не более чем общеупотребительное имя для первого параметра функции.источник