"Private" (Implementation) Class in Python

Private (implementation) class in Python

Use a single underscore prefix:

class _Internal:
...

This is the official Python convention for 'internal' symbols; "from module import *" does not import underscore-prefixed objects.

Reference to the single underscore convention.

Does Python have “private” variables in classes?

It's cultural. In Python, you don't write to other classes' instance or class variables. In Java, nothing prevents you from doing the same if you really want to - after all, you can always edit the source of the class itself to achieve the same effect. Python drops that pretence of security and encourages programmers to be responsible. In practice, this works very nicely.

If you want to emulate private variables for some reason, you can always use the __ prefix from PEP 8. Python mangles the names of variables like __foo so that they're not easily visible to code outside the namespace that contains them (although you can get around it if you're determined enough, just like you can get around Java's protections if you work at it).

By the same convention, the _ prefix means _variable should be used internally in the class (or module) only, even if you're not technically prevented from accessing it from somewhere else. You don't play around with another class's variables that look like __foo or _bar.

Calling private function within the same class python

There is no implicit this-> in Python like you have in C/C++ etc. You have to call it on self.

class Foo:
def __bar(self, arg):
#do something
def baz(self, arg):
self.__bar(arg)

These methods are not really private though. When you start a method name with two underscores Python does some name mangling to make it "private" and that's all it does, it does not enforce anything like other languages do. If you define __bar on Foo, it is still accesible from outside of the object through Foo._Foo__bar. E.g., one can do this:

f = Foo()
f._Foo__bar('a')

This explains the "odd" identifier in the error message you got as well.

You can find it here in the docs.

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

The name scrambling is used to ensure that subclasses don't accidentally override the private methods and attributes of their superclasses. It's not designed to prevent deliberate access from outside.

For example:

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

Of course, it breaks down if two different classes have the same name.

Private members in Python

9.6. Private Variables

“Private” instance variables that
cannot be accessed except from inside
an object, don’t exist in Python.
However, there is a convention that is
followed by most Python code: a name
prefixed with an underscore (e.g.
_spam) should be treated as a non-public part of the API (whether it
is a function, a method or a data
member). It should be considered an
implementation detail and subject to
change without notice.

Since there is a valid use-case for
class-private members (namely to avoid
name clashes of names with names
defined by subclasses), there is
limited support for such a mechanism,
called name mangling. Any identifier
of the form __spam (at least two
leading underscores, at most one
trailing underscore) is textually
replaced with _classname__spam, where
classname is the current class name
with leading underscore(s) stripped.
This mangling is done without regard
to the syntactic position of the
identifier, as long as it occurs
within the definition of a class.

So, for example,

class Test:
def __private_symbol(self):
pass
def normal_symbol(self):
pass

print dir(Test)

will output:

['_Test__private_symbol', 
'__doc__',
'__module__',
'normal_symbol']

__private_symbol should be considered a private method, but it would still be accessible through _Test__private_symbol.

Making a method private in a python subclass

Python is distributed as source. The very idea of a private method makes very little sense.

The programmer who wants to extend B, frustrated by a privacy issue, looks at the source for B, copies and pastes the source code for method into the subclass C.

What have you gained through "privacy"? The best you can hope for is to frustrate your potential customers into copying and pasting.

At worst, they discard your package because they can't extend it.

And yes, all open source is extended in one way or another. You can't foresee everything and every use to which you code will be put. Preventing some future use is hard to do when the code is distributed as source.

See How do I protect Python code?


Edit On "idiot-proof" code.

First, python is distributed as source 90% of the time. So, any idiot who downloads, installs, and then refuses to read the API guide and calls the methods out of order still has the source to figure out what went wrong.

We have three classes of idiots.

  • People who refuse to read the API guide (or skim it and ignore the relevant parts) and call the methods out of order in spite of the documentation. You can try to make something private, but it won't help because they'll do something else wrong -- and complain about it. [I won't name names, but I've worked with folks who seem to spend a lot of time calling the API's improperly. Also, you'll see questions like this on SO.]

    You can only help them with a working code sample they can cut and paste.

  • People who are confused by API's and call the methods every different way you can imagine (and some you can't.) You can try to make something private, but they'll never get the API.

    You can only help them by providing the working code sample; even then, they'll cut and paste it incorrectly.

  • People who reject your API and want to rewrite it to make it "idiot proof".

    You can provide them a working code sample, but they don't like your API and will insist on rewriting it. They'll tell you that your API is crazy and they've improved on it.

    You can engage these folks in an escalating arms race of "idiot-proofing". Everything you put together they take apart.

At this point, what has privacy done for you? Some people will refuse to understand it; some people are confused by it; and some people want to work around it.

How about public, and let the folks you're calling "idiots" learn from your code?

Python - Multiple private implementations for a class

Instead of composition, you could consider using a Abstract Base Class, with three different subclasses.
In python, duck typing is favoured over explicitly checking types.

Private methods in Python

Python doesn't have the concept of private methods or attributes. It's all about how you implement your class. But you can use pseudo-private variables (name mangling); any variable preceded by __(two underscores) becomes a pseudo-private variable.

From the documentation:

Since there is a valid use-case for class-private members (namely to
avoid name clashes of names with names defined by subclasses), there
is limited support for such a mechanism, called name mangling. Any
identifier of the form __spam (at least two leading underscores, at
most one trailing underscore) is textually replaced with
_classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard
to the syntactic position of the identifier, as long as it occurs
within the definition of a class.

class A:
def __private(self):
pass

So __private now actually becomes _A__private.

Example of a static method:

>>> class A:
... @staticmethod # Not required in Python 3.x
... def __private():
... print 'hello'
...
>>> A._A__private()
hello


Related Topics



Leave a reply



Submit