Почему «частные» методы Python на самом деле не являются частными?

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 не поддерживает инкапсуляцию, так зачем даже пытаться? Что дает?

То же самое верно для Java или C#, если вы используете отражение (что каким-то образом вы там делаете).

0x434D53 22.02.2015 13:24

Он был создан для целей модульного тестирования, поэтому вы можете использовать этот «хак» для модульного тестирования частных методов вашего класса извне.

waas1919 12.04.2016 19:10

Разве тестирование частных методов не является антипаттерном? Частные методы наверняка будут использоваться в некоторых общедоступных методах, иначе они просто не будут использоваться навсегда. И правильный способ тестирования частных методов (основанный на моих знаниях, полученных в ходе работы над ThoughtWorks) - это писать тесты только для общедоступных методов, которые охватывают все случаи. Если это работает нормально, вам вообще не нужно тестировать частные методы извне.

Vishnu Narang 23.01.2017 02:19

@VishnuNarang: Да, это то, чему часто учат. Но, как всегда, почти «религиозный» подход «всегда do this, никогда do that» - единственное, что «никогда» не годится. Если модульные тесты используются «только» для регрессионных тестов или тестирования общедоступного API, вам не нужно тестировать частные. Но если вы занимаетесь разработкой, управляемой модульными тестами, есть веские причины для тестирования приватных методов во время разработки (например, когда сложно имитировать определенные необычные / экстремальные параметры через общедоступный интерфейс). Некоторые языки / среды модульного тестирования не позволяют вам этого делать, что, IMHO, не очень хорошо.

Marco Freudenberger 13.02.2017 17:25

@MarcoFreudenberger Я понимаю вашу точку зрения. У меня есть опыт разработки, основанной на модульных тестах. Часто, когда становится сложно имитировать параметры, чаще всего это решается изменением и улучшением дизайна. Мне еще предстоит встретить сценарий, в котором дизайн был бы идеальным, и все же модульное тестирование чрезвычайно сложно избежать тестирования частных методов. Я буду следить за такими случаями. Спасибо. Я был бы признателен, если бы вы могли поделиться одним сценарием из головы, чтобы помочь мне понять.

Vishnu Narang 13.02.2017 21:56

У меня нет подходящего сценария, который прямо или косвенно не задействовал бы внешнее оборудование (например, я много работаю над системами машинного зрения, для определенных значений, передаваемых частным методам, необходимо создать определенные изображения, которые может быть сложно - потому что общедоступный интерфейс будет принимать изображения с камеры или из набора тестовых изображений в случае модульных тестов).

Marco Freudenberger 14.02.2017 23:21

Действительно хорошая идея, что все мы взрослые по согласию. Факт: в группе достаточно программистов, как и в любой другой группе, мудрость распространяется неравномерно. Если бы все знали все, stackoverflow не существовало бы. Вот еще одна цитата: «Я пришел к философии, а ушел к реальности».

omni 23.05.2018 22:16

@masi Плюс, если вы больше, чем простейшая кодовая обезьяна, вам придется манипулировать несколькими мыслями во время программирования. Чистые кодировщики делают методы небольшими, чтобы не помнить слишком много вещей. Если мне нужно подражать безопасности типов в голове, это еще одна вещь, которая отвлекает от сосредоточения внимания на архитектуре и алгоритмах.

Raphael Schmitz 20.02.2019 12:57

Разоблачая частные методы, питон, похоже, предпочитает «печень, свисающая из грудной клетки», хотя ему и предлагают «мы все взрослые, в Python мы доверяем».

Espresso 19.07.2019 05:38
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
701
9
462 175
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

От http://www.faqs.org/docs/diveintopython/fileinfo_private.html

Strictly speaking, private methods are accessible outside their class, just not easily accessible. Nothing in Python is truly private; internally, the names of private methods and attributes are mangled and unmangled on the fly to make them seem inaccessible by their given names. You can access the __parse method of the MP3FileInfo class by the name _MP3FileInfo__parse. Acknowledge that this is interesting, then promise to never, ever do it in real code. Private methods are private for a reason, but like many other things in Python, their privateness is ultimately a matter of convention, not force.

или, как выразился Гвидо ван Россум: «мы все взрослые».

user3850 06.10.2008 15:20

-1: это просто неправильно. Двойное подчеркивание никогда не предназначено для использования в первую очередь как закрытое. Ответ от Alya ниже показывает истинное намерение синтаксиса искажения имени. Настоящее соглашение - это одно подчеркивание.

nosklo 15.10.2009 18:02

Попробуйте использовать только одно подчеркивание, и вы увидите результат. @nosklo

Billal Begueradj 07.02.2017 12:56

Это не похоже на то, что вы абсолютно не можете обойти конфиденциальность членов на любом языке (арифметика указателей в C++, отражения в .NET / Java).

Дело в том, что вы получите ошибку, если попытаетесь случайно вызвать закрытый метод. Но если вы хотите прострелить себе ногу, сделайте это.

Обновлено: вы не пытаетесь защитить свои вещи с помощью OO-инкапсуляции, не так ли?

Нисколько. Я просто подчеркиваю, что было бы странно давать разработчику простой и, на мой взгляд, волшебный способ доступа к «частным» свойствам.

willurd 16.09.2008 13:11

Да, я просто попытался проиллюстрировать это. Если сделать его закрытым, это просто означает, что вы не должны обращаться к нему напрямую, заставляя компилятор жаловаться. Но действительно очень хочется сделать это, он может. Но да, на Python это проще, чем на большинстве других языков.

Maximilian 16.09.2008 13:26

В Java вы действительно можете защитить данные с помощью инкапсуляции, но для этого нужно быть умным, запускать ненадежный код в SecurityManager и быть очень осторожным. Даже Oracle иногда ошибается.

Antimony 24.04.2013 05:16

Соглашение об именах class.__stuff позволяет программисту знать, что он не предназначен для доступа к __stuff извне. Искажение имени делает маловероятным, что кто-то сделает это случайно.

Конечно, вы все еще можете обойти это, это даже проще, чем на других языках (которые, кстати, также позволяют вам это делать), но ни один программист Python не стал бы этого делать, если бы он заботился об инкапсуляции.

Это просто один из тех вариантов языкового дизайна. В какой-то степени они оправданы. Они делают это так, что вам нужно довольно далеко отойти от своего пути, чтобы попытаться вызвать метод, и если вам действительно это нужно так сильно, у вас должна быть довольно веская причина!

В качестве возможных приложений на ум приходят отладочные хуки и тестирование, которые, конечно же, используются ответственно.

Обычно используется фраза «мы все здесь взрослые по согласию». Добавляя одинарное подчеркивание (не раскрывать) или двойное подчеркивание (скрывать), вы сообщаете пользователю вашего класса, что хотите каким-то образом сделать этот член «частным». Однако вы доверяете всем остальным вести себя ответственно и уважать это, если только у них нет веских причин не делать этого (например, отладчики, автозавершение кода).

Если вам действительно нужно что-то частное, вы можете реализовать это в расширении (например, в C для CPython). Однако в большинстве случаев вы просто изучаете питонический образ действий.

так есть ли какой-то протокол-оболочка, который я должен использовать для доступа к защищенной переменной?

intuited 10.05.2010 22:56

«Защищенных» переменных нет больше, чем «частных». Если вы хотите получить доступ к атрибуту, который начинается с подчеркивания, вы можете просто сделать это (но обратите внимание, что автор этого не одобряет). Если вам необходимо получить доступ к атрибуту, который начинается с двойного подчеркивания, вы можете изменить имя самостоятельно, но вы почти наверняка не захотите этого делать.

Tony Meyer 13.05.2010 12:41
Ответ принят как подходящий

Скремблирование имен используется, чтобы гарантировать, что подклассы случайно не переопределят частные методы и атрибуты своих суперклассов. Он не предназначен для предотвращения преднамеренного доступа извне.

Например:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

Конечно, он не работает, если два разных класса имеют одно и то же имя.

docs.python.org/2/tutorial/classes.html. Section:9.6 on Private variables and class-local references.
gjain 17.10.2013 04:41

Для тех из нас, кому лень прокручивать / искать: Раздел 9.6 прямая ссылка

cod3monk3y 20.02.2014 08:22

Красиво - причина положительная! Я читал / слышал, что это было просто для предотвращения преднамеренного доступа извне (без фактического блокирования). Рад видеть, что есть и дополнительные преимущества.

Jon Coombs 15.03.2014 10:49

Вы должны поставить один знак подчеркивания, чтобы указать, что переменная должна рассматриваться как частная. Опять же, это не мешает кому-то получить к нему доступ.

igon 30.09.2014 01:31

@miya о да, это так, и он получил это от документация

Sнаđошƒаӽ 15.01.2016 20:55
Гвидо ответил на этот вопрос - "main reason for making (nearly) everything discoverable was debugging: when debugging you often need to break through the abstractions" - I added it as comment because it's too late -- too many answers.
Peter M. - stands for Monica 01.02.2016 22:02

Если следовать критерию «предотвратить преднамеренный доступ», большинство языков ООП не поддерживают действительно закрытые члены. Например, в C++ у вас есть прямой доступ к памяти, а в доверенном коде C# можно использовать частное отражение.

CodesInChaos 13.07.2016 13:40

Вот почему я никогда не балуюсь классами, интерфейс которых был разработан мной. Каждый, кто может его подклассифицировать, знает, над чем он работает, и, скорее всего, у него будет причина перегрузить определенные вещи, поэтому одного подчеркивания достаточно, чтобы сделать методы и свойства приватными. Я действительно использую dunders при реализации интерфейсов, разработанных другими, чтобы не загромождать api и предотвратить ошибки в случае, если они разделены на подклассы на основе знаний об их ABS. Хорошая причина для использования dunders - это, например, реализация io.BufferedIOBase, где ничего не должно мешать работе буферов.

Bachsau 28.11.2018 19:09

Обновление с Python 3.4: имя с префиксом подчеркивания (например, _spam) должно рассматриваться как закрытая часть API (будь то функция, метод или член данных). Это следует рассматривать как деталь реализации и может быть изменено без предварительного уведомления. docs.python.org/3/tutorial/classes.html#tut-private

Moradnejad 24.11.2020 14:11

Аналогичное поведение наблюдается, когда имена атрибутов модуля начинаются с одного символа подчеркивания (например, _foo).

Атрибуты модуля, названные как таковые, не будут скопированы в модуль импорта при использовании метода from*, например:

from bar import *

Однако это соглашение, а не языковое ограничение. Это не частные атрибуты; на них может ссылаться и манипулировать ими любой импортер. Некоторые утверждают, что из-за этого Python не может реализовать настоящую инкапсуляцию.

Когда я впервые перешел с Java на Python, я ненавидел this. Это до смерти напугало меня.

Сегодня это может быть только одна вещь Я люблю больше всего о Python.

Мне нравится находиться на платформе, где люди доверяют друг другу и не чувствуют, что им нужно строить непроницаемые стены вокруг своего кода. В строго инкапсулированных языках, если в API есть ошибка, и вы выяснили, что идет не так, вы все равно не сможете ее обойти, потому что необходимый метод является частным. В Python позиция такая: «конечно». Если вы думаете, что понимаете ситуацию, возможно, вы даже читали ее, тогда все, что мы можем сказать, - это «удачи!».

Помните, что инкапсуляция даже не слабо связана с «безопасностью» или защитой от детей на лужайке. Это просто еще один шаблон, который следует использовать, чтобы упростить понимание кода.

@CamJackson Javascript - ваш пример ?? Единственный широко используемый язык с наследованием на основе прототипов и языком, который поддерживает функциональное программирование? Я думаю, что JS намного сложнее выучить, чем большинство других языков, поскольку он требует нескольких шагов, ортогональных по сравнению с традиционным ООП. Не то чтобы это мешало идиотам писать JS, они просто этого не знают;)

K.Steff 10.04.2012 05:45

@Sudar Да, когда мы говорим о культуре принуждения программистов к написанию вещей определенным образом, Java, вероятно, является лучшей «противоположностью» Python в этом отношении. Но Javascript меня раздражает по-другому: P (см. Мой последний комментарий)

Cam Jackson 22.06.2012 15:16

API-интерфейсы на самом деле являются действительно хорошим примером того, почему инкапсуляция важна и когда предпочтительнее использовать частные методы. Метод, предназначенный как частный, может исчезнуть, изменить подпись или, что хуже всего, изменить поведение - и все это без предупреждения - в любой последующей новой версии. Будет ли ваш умный взрослый член команды действительно помнить, что через год, когда вы обновляете, она получила доступ к предполагаемому частному методу? Будет ли она там больше работать?

einnocent 10.01.2014 04:35

Я не согласен с этим аргументом. В производственном коде я, скорее всего, никогда не буду использовать API, в котором есть ошибка, которая заставляет меня менять публичные члены, чтобы заставить его «работать». API должен работать. Если этого не произойдет, я бы отправил отчет об ошибке или сам сделал тот же API. Мне не нравится эта философия, и я не очень люблю Python, хотя с его синтаксисом интересно писать небольшие скрипты на ...

Yngve Sneen Lindal 19.02.2014 15:45

Никто не заставляет вас использовать недокументированные API, но если вы этого хотите, кто вам скажет? Модульное тестирование приходит на ум как вариант использования.

Thomas Ahle 08.04.2014 17:07

В Java есть Method.setAccessible и Field.setAccessible. Также страшно?

Tony 24.04.2014 21:15

Принуждение в Java и C++ происходит не потому, что Java не доверяет пользователю, в то время как Python. Это потому, что компилятор и / или виртуальная машина могут делать различные предположения, имея дело с тем, как он ведет свои дела, если он знает эту информацию, например, C++ может пропустить весь уровень косвенного обращения, используя обычные старые вызовы C вместо виртуальных вызовов, и что имеет значение, когда вы работаете с высокопроизводительными или высокоточными материалами. Python по своей природе не может эффективно использовать информацию без ущерба для ее динамизма. Оба языка нацелены на разные вещи, поэтому ни один из них не является «неправильным».

Shayne 04.09.2016 14:25

Я противоположен твоему комментарию. Я пришел с Python и начал изучать Java и C++. Private - это не недоверие к товарищам по команде. Без типичных ошибок, когда новый разработчик в команде обращается к методу, выходящему за рамки бизнес-логики. то, что должно быть частным и вызываться специально с помощью некоторой логики, теперь стало общедоступным и может вызываться извне. еще страшнее, когда разработчик, совершающий эту ошибку, делает это на общедоступной конечной точке, открывая приложение для sec. уязвимости. Мне нравится питон, но я ненавижу этот его аспект.

continuousqa 01.03.2019 20:12

Это самое определение. может быть сек. недостаток. разработчики приходят и уходят командами. разработчику может быть поручено добавить общедоступную конечную точку, которая позволяет аффилированным лицам передавать новых регистрантов для создания пользователей. Однако сказал разработчик, перепрофилирует создание учетной записи, сделанное другими разработчиками. Класс создания учетной записи вызывает несколько методов, которые проверяют домены на предмет мошенничества. Но этот новый разработчик напрямую обращается к финальному методу, передавая значение для проверки домена. теперь общедоступная конечная точка обходит проверки на мошенничество. Если бы этот последний метод был частным, ничего бы этого не произошло. это заставит его течь через автобус. логика.

continuousqa 01.03.2019 20:18

Мы не делаем методы частными и общедоступными в целях безопасности. Мы делаем их, чтобы пользователи не могли нанести серьезный ущерб состоянию и писать программы с использованием изменчивых методов. Открытый метод представляет собой контракт, если я дам вам A, вы получите B. Частные методы не представляют собой контракт. Я могу изменить логику, которая превращает A в B, сколько мне нужно, пока интерфейс взаимодействия по-прежнему выполняет контракт. Если я дам вам доступ к частным методам, вы будете их использовать. Затем, когда я меняю реализацию, ваша программа ломается. Этого не происходит с общедоступными методами, составляющими контракт.

TheBatman 23.04.2019 21:11

"Мне нравится находиться на платформе, где люди доверяют друг другу и не чувствуют, что им нужно строить непроницаемые стены вокруг своего кода." Полная чушь. Отказ от установленных принципов дизайна не заставит ваших коллег полюбить вас, это как раз наоборот. Python во многих отношениях никогда не достигнет структуры и формализма типизированных языков JVM или функционального чутья Haskell. Это хорошо для некоторых вещей, но не нужно красить свинью помадой.

Abhijit Sarkar 26.08.2020 04:14

@einnocent Меня не убеждает, что приватный метод может измениться в любой момент без уведомления. Фактически то же самое можно применить и к Python, docs.python.org/3/tutorial/classes.html#tut-private, _underscore_method() следует рассматривать как деталь реализации. Таким образом, потребитель класса должен принять во внимание, что он может измениться в любой момент. Если кто-то использует ваши частные методы в своем производственном коде, то это не ваша проблема, если вы измените свои личные данные.

Qback 31.08.2020 20:20

Самая большая ошибка Java заключалась в том, чтобы не различать общедоступный и опубликованный метод (метод, который должен вызываться извне jar), соединение python в этой ошибке делает все видимым. В любом достаточно большом проекте управление релизами и зависимостями превращается в полный кошмар (добавьте сверху, что некоторые ошибки могут быть обнаружены только во время выполнения, а тикающая бомба обслуживается)

Alessandro Teruzzi 18.09.2020 14:04

Пример частной функции

import re
import inspect

class MyClass :

    def __init__(self) :
        pass

    def private_function ( self ) :
        try :
            function_call = inspect.stack()[1][4][0].strip()

            # See if the function_call has "self." in the begining
            matched = re.match( '^self\.', function_call )
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except :
            print 'This is Private Function, Go Away'
            return

        # This is the real Function, only accessible inside class #
        print 'Hey, Welcome in to function'

    def public_function ( self ) :
        # i can call private function from inside the class
        self.private_function()

### End ###

self = MyClass()self.private_function(). : D Конечно, это не работает в классах, но вам просто нужно определить пользовательскую функцию: def foo(self): self.private_function()

Casey Kuball 08.05.2012 20:34

На всякий случай непонятно: никогда делает это в реальном коде;)

Sudo Bash 12.07.2013 19:40

Я бы не стал загружать регулярное выражение только для того, чтобы проверить выражение /^.../, сэкономить время и использовать 0 == function_call.index('self.').

ThorSummoner 03.07.2014 03:32

@ThorSummoner Или просто function_call.startswith('self.').

nyuszika7h 27.08.2014 12:52

inspect.stack()[1][4][0].strip() <- что это за магические числа 1, 4 и 0?

akhy 23.06.2016 10:36

self - это всего лишь условность. можно использовать другое имя для первого аргумента

akiva 18.07.2016 03:40

@arun, почему 1 4 0?

Iulian Onofrei 21.04.2017 16:45

но когда я вызываю obj.public_function () ... он все еще показывает «Это закрытая функция, уходи». не должен ли он показывать «добро пожаловать в работу»

Jai 30.05.2017 11:11

@SudoBash - идиотский вопрос: почему бы не использовать это в реальном коде?

Shuklaswag 07.02.2018 22:28

@Shuklaswag Это усложняет работу с вашим кодом, поскольку создает препятствия на пути его отладки. Попытки обойти правила языка с ненужной смекалкой редко заканчиваются хорошо. (Он также не блокирует публичные вызовы функции).

Will 22.11.2018 05:49

Эту проблему можно довольно легко решить, выполнив self = MyClass(); self.private_function(), и она не работает при вызове с использованием x = self.private_function() внутри метода.

Will 22.11.2018 05:58

не уверен, что понимаю этот ответ. Он демонстрирует, как иметь действительно частный метод, но не отвечает на вопрос «почему у pyhthon нет действительно частных методов?», Верно?

largest_prime_is_463035818 22.01.2019 18:34

В Python 3.4 это поведение:

>>> class Foo:
        def __init__(self):
                pass
        def __privateMethod(self):
                return 3
        def invoke(self):
                return self.__privateMethod()


>>> help(Foo)
Help on class Foo in module __main__:

class Foo(builtins.object)
 |  Methods defined here:
 |
 |  __init__(self)
 |
 |  invoke(self)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables (if defined)
 |
 |  __weakref__
 |      list of weak references to the object (if defined)

 >>> f = Foo()
 >>> f.invoke()
 3
 >>> f.__privateMethod()
 Traceback (most recent call last):
   File "<pyshell#47>", line 1, in <module>
     f.__privateMethod()
 AttributeError: 'Foo' object has no attribute '__privateMethod'

https://docs.python.org/3/tutorial/classes.html#tut-private

Note that the mangling rules are designed mostly to avoid accidents; it still is possible to access or modify a variable that is considered private. This can even be useful in special circumstances, such as in the debugger.

Даже если вопрос старый, я надеюсь, что мой фрагмент может быть полезен.

Самая важная проблема, связанная с частными методами и атрибутами, - сказать разработчикам, чтобы они не вызывали их вне класса, и это инкапсуляция. можно неправильно понять безопасность от инкапсуляции. когда кто-то намеренно использует подобный синтаксис (ниже), о котором вы упомянули, вам не нужна инкапсуляция.

obj._MyClass__myPrivateMethod()

Я перешел с C#, и сначала для меня это тоже было странно, но через некоторое время я пришел к мысли, что только то, как разработчики кода Python думают о ООП, отличается.

Why are Python's 'private' methods not actually private?

Насколько я понимаю, они не могу приватные. Как можно обеспечить конфиденциальность?

Очевидный ответ - «к закрытым членам можно получить доступ только через self», но это не сработает - self не является особенным в Python, это не что иное, как обычно используемое имя для первого параметра функции.

Важное обновление (Python 3.4):

Любой идентификатор в форме __name (не менее двух ведущих подчеркиваний, не более одного подчеркивания в конце) публично заменяется на _classname__name, где classname - это имя текущего класса с удаленными ведущими подчеркиваниями.

Следовательно, __name является частным, а _classname__name - публичным.

https://docs.python.org/3/tutorial/classes.html#tut-private

Пример

class Cat:
    def __init__(self, name='unnamed'):
        self.name = name
    def __print_my_name(self):
        print(self.name)
        
        
tom = Cat()
tom.__print_my_name() #Error
tom._Cat__print_my_name() #Prints name

Другие вопросы по теме