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

Python gives us the ability to create 'private' methods and variables within a class by prepending double underscores to the name, like this: __myPrivateMethod(). How, then, can one explain this

>>>> 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!!

What's the deal?!

I'll explain this a little for those who didn't quite get that.

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
...
>>> obj = MyClass()

I create a class with a public method and a private method and instantiate it.

Next, I call its public method.

>>> obj.myPublicMethod()
public method

Next, I try and call its private method.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

Everything looks good here; we're unable to call it. It is, in fact, 'private'. Well, actually it isn't. Running dir() on the object reveals a new magical method that Python creates magically for all of your 'private' methods.

>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

This new method's name is always an underscore, followed by the class name, followed by the method name.

>>> obj._MyClass__myPrivateMethod()
this is private!!

So much for encapsulation, eh?

In any case, I'd always heard Python doesn't support encapsulation, so why even try? What gives?

← Назад к списку