Does Python Have "Private" Variables in Classes

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 class 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 stay away even if you're not technically prevented from doing so. You don't play around with another class's variables that look like __foo or _bar.

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).

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.

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.

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

What is the point of using private variables if we also use the property decorator in Python?

Think like this:

Define your attribute as public name, because well, there is way to make it private in Python.

class Product:

def __init__(self, name):
self.name = name

If name is an implementation detail of your class, hint that to the class users by renaming it to _name. Nothing changes, this is only a convention saying, "this is for internal use only, and can change in the future; do not touch, or go ahead at your own risk".

class Product:

def __init__(self, name):
self._name = name

If you want to annoy a bit your class users, rename it to __name. This is discouraged by many Pythonists, because it does not prevent access, it justs causes an error on direct access (this is actually meant to mangle the name with the class name to prevent clashes, not give privacy).

class Product:

def __init__(self, name):
self.__name = name

>>> p = Product("Cube")
>>> p.__name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Product' object has no attribute '__name'
>>> p._Product__name
'Cube'

Instead, and if you want to make an attribute read-only, define a property name, changing the the underlying name to _name (the internal class value you return in your getter).

class Product:

def __init__(self, name):
# hint privacy only, using _
self._name = name

@property
def name(self):
return self._name

If you actually want it to be changed too, define the property setter, making it writable on one hand, and allowing the execution of validation code, a common requirement when you allow writes. Both the getter and the setter can be used to intercept attribute access at runtime, and run additional code with whatever class internal side effects you might need.

       @name.setter
def name(self, value):
# maybe validate the value
if name_is_valid(value):
self._name = value
else:
raise ValueError("Invalid Product name")

This is what you actually need to know to use properties most of the time, without having to worry about decorators and descriptors (an advanced concept, properties are actually a descriptor).

Access to **private** variables of a class in Python

It's because variables starting with a dunder are name mangled to "protect" them. If you examine the dictionary of bClass, you'll see:

>>> print(bClass.__dict__)
{'_BClass__x': 10, '__x': 20}

The _BClass__x (I'll call this the object variable) was created by the object itself, hence its mangled name. The __x was created outside of the class(a) which is why it has a non-mangled name, and therefore why you can access it with just __x.

To access the object variable for both types, you can use:

print (aClass._AClass__x)
print (bClass._BClass__x)

But I'm not sure how reliable that is. I am sure that it's something you probably shouldn't be doing however, since it breaks encapsulation :-)

In fact, though I said the mangling was done by the object, I want to make sure you understand it's not done when an object is instantiated. The actual mangling happens when the code is compiled, which you can see if you disassemble:

>>> import dis
>>> dis.dis(AClass)
Disassembly of __init__:
3 0 LOAD_FAST 1 (x)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (_AClass__x)
6 LOAD_CONST 0 (None)
8 RETURN_VALUE

The STORE_ATTR bytecode actually knows to use a mangled name.


(a) And it is very much distinct from the object variable, as you'll find to your distress when you later try to use __x within a member function and find it hasn't been changed by your code outside :-)

Do non-existing private variables make python less secure than C#?

Member accessibility is not a security feature. It's a tool to aid programmers by helping programmers understand how a given member is intended to be used by its author. If someone is in a position of being able to run privileged code on a machine then there are no language features to prevent them from accessing the data. You can make it harder, you can make it inconvenient to access the data in question. But you can't prevent it.

If a programmer is using a library of yours then there is nothing you can do to stop them from accessing and changing any of the "private" data in your code. If they're doing so then they're simply doing so with the knowledge that they can no longer rely on your code to work correctly. It's the morale equivalent of taking apart something you bought, tinkering with it, and then putting it back together again. You might break something if you do it wrong, and (most things) aren't designed to have you do this, but they can't stop you from doing it.

If you're writing code, and need the private data it's storing to be inaccessible to your end users, then you can't let them run it on their machines. You need to have them make a request to your server, run your sensitive code, keeping all of the information you don't want them to have access to entirely on your own private server, and then sending them a response with whatever resulting information you want them to be able to have.

This is, with very few exceptions, true of all languages.



Related Topics



Leave a reply



Submit