Private Members in Python

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.

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.

Truly Private Variables in Python 3

I have tried overriding getattribute, but the problem is that there is no way to tell if the call is coming from inside the class or not (that I am aware of).

You can use the inspect module to find the name and module of the calling function, which you could compare against a whitelist.

But inspect also has getattr_static, which can bypass any __getattribute__.


Nothing is truly private in Python. There are ways to make access difficult, but there are always ways around those ways.

The only solution then, is outside of the current Python interpreter. You could use a foreign function interface to some other more secure language or a remote procedure call (e.g. xmlrpc) to the same or to another Python interpreter running in a subprocess, or even one running as a different user with different permissions. The private variable and all the functions allowed to access it will live outside the current interpreter. Then there's no way to inspect it.

This type of privilege separation is even one of the stated use cases for the Pyro RPC library.

Declaring private variable in Python

In short: there is no way to have a truly "private" class member in Python. The runtime simply doesn't support memory protection in the way, ex, Java does.

The double underscore prefix mangles the name so it includes the name of the class it's used in (ex, __total would become _Balance__total), but this is primarily used to allow subclasses to define names which appear the same, but reference different fields.

The standard convention in Python is to use a single underscore prefix — _total — for class members which should be treated as be "private" or "protected", then trust that the other developers will be adults and respect that (of course, this isn't always a safe assumption…)

It is very rare to see modern Python code use double-underscore attributes.

How Do I Make Private Variables Inaccessable in Python?

What you are trying to do is not possible in Python.

“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python.

https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

public or private attribute in Python ? What is the best way?

Typically, Python code strives to adhere to the Uniform Access Principle. Specifically, the accepted approach is:

  • Expose your instance variables directly, allowing, for instance, foo.x = 0, not foo.set_x(0)
  • If you need to wrap the accesses inside methods, for whatever reason, use @property, which preserves the access semantics. That is, foo.x = 0 now invokes foo.set_x(0).

The main advantage to this approach is that the caller gets to do this:

foo.x += 1

even though the code might really be doing:

foo.set_x(foo.get_x() + 1)

The first statement is infinitely more readable. Yet, with properties, you can add (at the beginning, or later on) the access control you get with the second approach.

Note, too, that instance variables starting with a single underscore are conventionally private. That is, the underscore signals to other developers that you consider the value to be private, and they shouldn't mess with it directly; however, nothing in the language prevents them from messing with it directly.

If you use a double leading underscore (e.g., __x), Python does a little obfuscation of the name. The variable is still accessible from outside the class, via its obfuscated name, however. It's not truly private. It's just kind of ... more opaque. And there are valid arguments against using the double underscore; for one thing, it can make debugging more difficult.

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.

Does python support private variables?

There is a lot of literature on this topic, but in short:

Python is different to programming languages that have actually "private" attributes in that no attribute can be truly inaccessible by other functions. Yes, we can simulate the behaviour of languages like Java using property, as you've shown, but that is kind of fudging "true" private attributes. What property actually is is a higher-order function (well, technically, it's a decorator), so when you call c.x, although it acts as a property, you're really referring to a function that controls whether you can use the getters and setters defined in it.

But just because c.x doesn't allow direct read access, doesn't mean that you can't call print c._x (as @avigil pointed out). So c._x isn't really private - it's just as easily accessible as any other attribute belonging to the C class. The fact that its name starts with an underscore is just a convention - a signal to fellow programmers: "Please don't handle this variable directly, and use the getters/setters instead" (if available).

Access private variables in injected method - python

The name mangling of "private" members is strictly done within class definitions. To achieve the desired purpose, which is to have self.__hidden translated to self._Simulation_hidden you need simply define it within an appropriately named class.

For example:

def make_mocked_method():
class Simulation:
# this is your code, but now its inside a class stanza so '__' will be mangled
def mocked_method(self):
print(type(self))
print(self.__dict__)
print(self.__hidden)

return Simulation.mocked_method

Now mocked_method will access the desired attribute correctly:

simulation.mocked_update = MethodType(make_mocked_method(), simulation)
simulation.someloop()

gives:

<class '__main__.Simulation'>
{'finished': False, 'mocked_update': <bound method make_mocked_method.<locals>.Simulation.mocked_method of <__main__.Simulation object at 0x101c00a58>>, '_Simulation__hidden': -10}
-10

Extension

This relies on us hard coding the name of the class we're adding the method to (Simulation). To avoid that we can instead use an exec:

def make_mocked_method(cls):
txt = """class {}:
def mocked_method(self):
print(type(self))
print(self.__dict__)
print(self.__hidden)
""".format(cls.__name__)
ns = {}
exec(txt, ns)
return ns[cls.__name__].mocked_method

Unfortunately here the function we wish to add must be defined as text, it can't be some already defined arbitrary function object. (That might possibly be solved by using inspect to find its source and then recompiling that source within a class stanza using exec (and judicious choice of globals).

Defining private module functions in python

In Python, "privacy" depends on "consenting adults'" levels of agreement - you can't force it (any more than you can in real life;-). A single leading underscore means you're not supposed to access it "from the outside" -- two leading underscores (w/o trailing underscores) carry the message even more forcefully... but, in the end, it still depends on social convention and consensus: Python's introspection is forceful enough that you can't handcuff every other programmer in the world to respect your wishes.

((Btw, though it's a closely held secret, much the same holds for C++: with most compilers, a simple #define private public line before #includeing your .h file is all it takes for wily coders to make hash of your "privacy"...!-))



Related Topics



Leave a reply



Submit