Private members in Python

How can I make methods and data members private in Python? Or does Python support private members?

+61
python oop class member-variables
Jan 14
source share
9 answers

9.6. Private variables

"Private" instance variables that cannot be accessed except from inside the object do not exist in Python. However, there is a convention that is followed by most Python code: a name with an underscore prefix (for example, _spam) should be considered as a non-public part of the API (be it a function, method, or member data). It should be considered as implementation details and changed without notice.

Since there is a valid precedent for members of a private class (namely, to avoid names, name conflicts with names is determined by subclasses), there is limited support for such a mechanism, the so-called name mangling. Any __spam form identifier (at least two leading underscores, no lower underscore) is replaced with a text one by _classname__spam , where classname is the name of the current class with leading underscore (s). This manipulation is performed regardless of the syntactic position of the identifier, if this happens in the class definition.

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 as a private method, but it will still be available through _Test__private_symbol .

+74
Jan 14 '10 at 13:08
source share

Other answers contain technical details. I would like to emphasize the difference in philosophy between Python, on the one hand, and languages ​​such as C ++ / Java (which, I suppose, you are familiar with your question).

The general relation to Python (and Perl for that matter) is that the "confidentiality" of the attribute is a request to the programmer, not a barbed wire due to the compiler / interpreter. The idea is well generalized in this post and is often referred to as “We all agree with adults” because it “assumes” that the programmer is responsible enough not to interfere in internal affairs. Leading underscores provide a polite message that the attribute is internal.

On the other hand, if you want to access internal components for some applications (a notable example is documentation generators like pydoc), you can do this. Onus, as a programmer, knows what you are doing, and do it right, not in the language, to make you do it like this.

+32
Jan 14 '10 at 13:39
source share

If a Python function name, class method, or attribute begins with (but does not end) with two underscores, this is a quotient; everything else is open. Python has no concept of methods of a protected class (available only in its class and descendant classes). Class methods are private (available only in their own class) or public (available from anywhere).

Python immersion

+6
Jan 14
source share

There are no private access protection mechanisms in Python. The Python style guide has documented a convention that tells users of your class that they should not access certain attributes.

  • _single_leading_underscore: weak indicator of "internal use". For example, from M import * objects whose name begins with an underscore are not imported.

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

  • __double_leading_underscore: when naming a class attribute, it causes name distortion (inside the FooBar __boo class, _FooBar__boo becomes; see below).

+6
Jan 14 '10 at 13:41
source share

Python does not support privacy directly. The programmer needs to know when it is safe to change the attribute from the outside, but in any case, using python you can achieve something like private with little tricks. Now let's see that a person can put something personal in him 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 that we have done:

 >>> 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 can someone access this variable ??? You can do this:

 >>> p._Person__priva
 I am private

wow, in fact, if python gets any variable starting with a double underscore, it is "translated" by adding a single underscore and class name to the beginning:

Note. . If you do not want this name to change, but you still want to send a signal to other objects in order to stay away, you can use the same underscore starting name with the original underscore imported using (from module import *)
Example:

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

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

exit →

 hello
 Traceback (most recent call last):
   File "", line 1, in 
 NameError: name '_hello' is not defined

Now, if we call _hello manually.

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

exit →

 hello
 hello private

Finally: Python doesn't really have equivalent privacy support, although single and double initial underscores give you two levels of privacy to a certain extent.

+5
Dec 27 '13 at 5:51 on
source share

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() 
+2
Feb 03 '17 at 19:44
source share

This is kind of a long answer, but I think it gets to the root of the real problem - scope. Just hang there while I scroll through it!

Simply importing a module does not have to give the application developer access to all its classes or methods; if I cannot SEE the source code of the module, how do I know what is available? Someone (or some THING) should tell me what I can do and explain how to use the functions that I am allowed to use, otherwise all this is useless to me.

Those who develop higher-level abstractions based on fundamental classes and methods using imported modules are represented by the DOCUMENT specification - NOT the actual source code.

The module specification describes all the functions that should be visible to the client developer. When working with large projects and software projects, the actual implementation of the module should ALWAYS remain hidden from those who use it - this is a black box with an interface to the outside world. For OOD purists, I think techie terms are “decoupling” and “cohesion.” The user of the module should know only the interface methods, not burdening with implementation details.

A module should NEVER be changed without first changing its underlying specification document, which may require review / approval by some organizations before changing the code.

As a hobby programmer (now retired), I launched a new module in which the specified document is actually written out as a giant block of comments at the top of the module, this will be the part that the user really sees in the specification library. Since it's just me, I haven't created a library yet, but that would be easy enough to do.

Then I start coding, writing down various classes and methods, but without functional bodies - just zero print statements such as "print ()" - enough for the module to compile without syntax errors. When this step is complete, I compile the completed null module - this is my specification. If I were working on a project team, I would present this specification / interface for review and comments before proceeding with body phishing.

I form the bodies of each method one at a time and compile accordingly, ensuring that syntax errors are fixed immediately on the fly. This is also a good time to start recording the temporary “main” stage of execution below to test each method as it is encoded. When coding / testing is complete, the entire test code is commented out until it is needed if updates become necessary.

In a real development team, a comment comment block will also appear in the document management library, but that's another story. The fact is that you, as a module client, see only this specification and NOT the source code.

PS: long before the start of work, I worked in the defense aerospace community, and we did pretty cool things, but things like patented algorithms and control logic of sensitive systems were hard-coded and encrypted in super-duper protected software libraries. We had access to the module / package interfaces, but not to the black box implementation areas. There was a document management tool that processed all projections at the system level, software specifications, source code, and test records — everything was synchronized together. The government had strict requirements for software quality assurance standards. Does anyone remember a language called Ada? That's how old I am!

+2
Feb 12 '17 at 2:34 on
source share

I am using 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) 

launched it and received:

AttributeError: 'MyOBject' does not have '__private_field' attribute

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

0
May 22 '19 at 19:42
source share

if you want methods or data members to be private in Python use __setattr __

 class Number: def __init__(self,value): self.my_private = value def __setattr__(self, my_private, value): # the default behavior # self.__dict__[my_private] = value raise Exception("can't access private member-my_private") def main(): n = Number(2) print(n.my_private) if __name__ == '__main__': main() 
-one
Oct 21 '15 at 13:50
source share



All Articles