Private members in Python

Question:

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

Asked By: appusajeev

||

Answers:

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

Answered By: Svetlozar Angelov

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.

Answered By: jbochi

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.

Answered By: Noufal Ibrahim

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

Answered By: Tendayi Mawushe

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

Answered By: Prashant Gaur
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()
Answered By: liorb87

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()
Answered By: Laszlo

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!

Answered By: We_Are_Borg

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

Answered By: CrazySynthax

PEP 8

Section "Method Names and Instance Variables" https://peps.python.org/pep-0008/#method-names-and-instance-variables

Use one leading underscore only for non-public methods and instance variables.

To avoid name clashes with subclasses, use two leading underscores to invoke Python’s name mangling rules.

Python mangles these names with the class name: if class Foo has an attribute named __a, it cannot be accessed by Foo.__a. (An insistent user could still gain access by calling Foo._Foo__a.) Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed.

Note: there is some controversy about the use of __names (see below).

Section "Designing for Inheritance
" https://peps.python.org/pep-0008/#designing-for-inheritance

Always decide whether a class’s methods and instance variables (collectively: “attributes”) should be public or non-public. If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public.

Public attributes are those that you expect unrelated clients of your class to use, with your commitment to avoid backwards incompatible changes. Non-public attributes are those that are not intended to be used by third parties; you make no guarantees that non-public attributes won’t change or even be removed.

We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).

Another category of attributes are those that are part of the “subclass API” (often called “protected” in other languages). Some classes are designed to be inherited from, either to extend or modify aspects of the class’s behavior. When designing such a class, take care to make explicit decisions about which attributes are public, which are part of the subclass API, and which are truly only to be used by your base class.

With this in mind, here are the Pythonic guidelines:

  • Public attributes should have no leading underscores.

  • If your public attribute name collides with a reserved keyword, append a single trailing underscore to your attribute name. This is preferable to an abbreviation or corrupted spelling. (However, notwithstanding this rule, ‘cls’ is the preferred spelling for any variable or argument which is known to be a class, especially the first argument to a class method.)

    Note 1: See the argument name recommendation above for class methods.

  • For simple public data attributes, it is best to expose just the attribute name, without complicated accessor/mutator methods. Keep in mind that Python provides an easy path to future enhancement, should you find that a simple data attribute needs to grow functional behavior. In that case, use properties to hide functional implementation behind simple data attribute access syntax.

    Note 1: Try to keep the functional behavior side-effect free, although side-effects such as caching are generally fine.

    Note 2: Avoid using properties for computationally expensive operations; the attribute notation makes the caller believe that access is (relatively) cheap.

  • If your class is intended to be subclassed, and you have attributes that you do not want subclasses to use, consider naming them with double leading underscores and no trailing underscores. This invokes Python’s name mangling algorithm, where the name of the class is mangled into the attribute name. This helps avoid attribute name collisions should subclasses inadvertently contain attributes with the same name.

    Note 1: Note that only the simple class name is used in the mangled name, so if a subclass chooses both the same class name and attribute name, you can still get name collisions.

    Note 2: Name mangling can make certain uses, such as debugging and getattr(), less convenient. However the name mangling algorithm is well documented and easy to perform manually.

    Note 3: Not everyone likes name mangling. Try to balance the need to avoid accidental name clashes with potential use by advanced callers.

Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.