Private members in Python

PythonClassOopMember Variables

Python Problem Overview


How can I make methods and data members private in Python? Or doesn't Python support private members?

Python Solutions


Solution 1 - 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.

Solution 2 - Python

The other answers provide the technical details. I'd like to emphasise the difference in philosophy between Python on one hand and languages like C++/Java (which I presume you're familiar with based on your question).

The general attitude in Python (and Perl for that matter) is that the 'privacy' of an attribute is a request to the programmer rather than a barbed wire fence by the compiler/interpreter. The idea is summarised well in this mail and is often referred to as "We're all consenting adults" since it 'assumes' that the programmer is responsible enough to not meddle with the insides. The leading underscores serve as a polite message saying that the attribute is internal.

On the other hand, if you do want to access the internals for some applications (a notable example is documentation generators like pydoc), you're free to do so. Onus is on you as a programmer to know what you're doing and do it properly rather than on the language to force you do to things it's way.

Solution 3 - Python

There are no private of any other access protection mechanisms in Python. There is a convention documented in the Python style guide for indicating to the users of your your class that they should not be accessing certain attribute.

  • _single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

  • single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g. Tkinter.Toplevel(master, class_='ClassName')

  • __double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

Solution 4 - Python

> If the name of a Python function, > class method, or attribute starts with > (but doesn't end with) two > underscores, it's private; everything > else is public. Python has no concept > of protected class methods (accessible > only in their own class and descendant > classes). Class methods are either > private (accessible only in their own > class) or public (accessible from > anywhere).

Dive Into Python

Solution 5 - Python

Python does not support privacy directly . Programmer need to know when it is safe to modify attribute from outside but anyway with python you can achieve something like private with little tricks. Now let's see a person can put anything private to it or not.

class Person(object):

    def __priva(self):
        print "I am Private"
   
    def publ(self):
        print " I am public"
   
    def callpriva(self):
        self.__priva()

Now When we will execute :

>>> p = Person()
>>> p.publ()
I am public
>>> p.__priva()
Traceback (most recent call last):
File "", line 1, in 
p.__priva()
AttributeError: 'Person' object has no attribute '__priva'
​#Explanation   : You can see  here we are not able to fetch that private method directly.
>>> p.callpriva()
I am Private
#​Explanation  : Here we can access private method inside class​

​Then how someone can access that variable ???
You can do like :

>>> p._Person__priva
I am Private
​wow , actually if python is getting any variable starting with double underscore are “translated” by adding a single underscore and the class name to the beginning:

Note : If you do not want this name changing but you still want to send a signal for other objects to stay away, you can use a single initial underscore names with an initial underscore aren’t imported with starred imports (from module import *)
Example :

#test.py
def hello():
    print "hello"
def _hello():
    print "Hello private"

#----------------------
#test2.py
from test import *
print hello()
print _hello()

output-->

hello
Traceback (most recent call last):
File "", line 1, in 
NameError: name '_hello' is not defined
Now if we will call _hello manually .

#test2.py
from test import _hello , hello
print hello()
print _hello()

output-->

hello
hello private

Finally : Python doesn’t really have an equivalent privacy support, although single and double initial underscores do to some extent give you two levels of privacy

Solution 6 - Python

This might work:

import sys, functools

def private(member):
    @functools.wraps(member)
    def wrapper(*function_args):
      myself = member.__name__
      caller = sys._getframe(1).f_code.co_name
      if (not caller in dir(function_args[0]) and not caller is myself):
         raise Exception("%s called by %s is private"%(myself,caller))
      return member(*function_args)
    return wrapper

class test:
   def public_method(self):
      print('public method called')

   @private
   def private_method(self):
      print('private method called')

t = test()
t.public_method()
t.private_method()

Solution 7 - Python

This is kinda a l-o-n-g answer but I think it gets to the root of the real problem here -- scope of visibility. Just hang in there while I slog through this!

Simply importing a module need not necessarily give the application developer access to all of its classes or methods; if I can't actually SEE the module source code how will I know what's available? Some one (or some THING) has to tell me what I can do and explain how to use those features I'm allowed to use, otherwise the whole thing is useless to me.

Those developing higher-level abstractions based on fundamental classes and methods via imported modules are presented with a specification DOCUMENT -- NOT the actual source code.

The module spec describes all the features intended to be visible to the client developer. When dealing with large projects and software project teams, the actual implementation of a module should ALWAYS remain hidden from those using it -- it's a blackbox with an interface to the outside world. For OOD purists, I believe the techie terms are "decoupling" and "coherence". The module user need only know the interface methods without being burden with the details of implementation.

A module should NEVER be changed without first changing its underlying spec document, which may require review / approval in some organizations prior to changing the code.

As hobby programmer (retired now), I start a new module with the spec doc actually written out as a giant comment block at the top of the module, this will be the part the user actually sees in the spec library. Since it's just me, I've yet to set up a library, but it would be easy enough to do.

Then I begin coding by writing the various classes and methods but without functional bodies -- just null print statements like "print()" -- just enough to allow the module to compile without syntax errors. When this step is complete I compile the completed null-module -- this is my spec. If I were working on a project team, I would present this spec/interface for review & commentary before proceeding with fleshing out the body.

I flesh out the bodies of each method one at a time and compile accordingly, ensuring syntax errors are fixed immediately on-the-fly. This is also a good time to start writing a temporary "main" execution section at the bottom to test each method as you code it. When the coding/testing are complete, all of the test code is commented out until you need it again should updates become necessary.

In a real-world development team, the spec comment block would also appear in a document control library, but that's another story. The point is: you, as the module client, see only this spec and NOT the source code.

PS: long before the beginning of time, I worked in the defense aerospace community and we did some pretty cool stuff, but things like proprietary algorithms and sensitive systems control logic were tightly vaulted and encrypted in super-duper secure software libraries. We had access to module / package interfaces but NOT the blackbox implementation bodies. There was a document management tool that handled all system-level designs, software specs, source code and test records -- it was all synched together. The government had strict requirements software quality assurance standards. Anyone remember a language called "Ada"? That's how old I am!

Solution 8 - Python

import inspect


class Number:
    def __init__(self, value):
        self.my_private = value

    def set_private(self, value):
        self.my_private = value

    def __setattr__(self, my_private, value):
        f = inspect.stack()[1][3]
        if f not in ['__init__', 'set_private']:
            raise Exception("can't access private member-my_private")
        # the default behavior
        self.__dict__[my_private] = value


def main():
    n = Number(2)
    print(n.my_private)
    n.set_private(3)
    print(n.my_private)


if __name__ == '__main__': 
    main()

Solution 9 - Python

I use Python 2.7 and 3.5. I wrote this code:

class MyOBject(object):
    def __init__(self):
        self.__private_field = 10


my_object = MyOBject()
print(my_object.__private_field)

ran it and got:

> AttributeError: 'MyOBject' object has no attribute '__private_field'

Please see: https://www.tutorialsteacher.com/python/private-and-protected-access-modifiers-in-python

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionappusajeevView Question on Stackoverflow
Solution 1 - PythonjbochiView Answer on Stackoverflow
Solution 2 - PythonNoufal IbrahimView Answer on Stackoverflow
Solution 3 - PythonTendayi MawusheView Answer on Stackoverflow
Solution 4 - PythonSvetlozar AngelovView Answer on Stackoverflow
Solution 5 - PythonPrashant GaurView Answer on Stackoverflow
Solution 6 - PythonLaszloView Answer on Stackoverflow
Solution 7 - PythonWe_Are_BorgView Answer on Stackoverflow
Solution 8 - Pythonliorb87View Answer on Stackoverflow
Solution 9 - PythonCrazySynthaxView Answer on Stackoverflow