741

I'm coming from the Java world and reading Bruce Eckels' Python 3 Patterns, Recipes and Idioms.

While reading about classes, it goes on to say that in Python there is no need to declare instance variables. You just use them in the constructor, and boom, they are there.

So for example:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

If that’s true, then any object of class Simple can just change the value of variable s outside of the class.

For example:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

In Java, we have been taught about public/private/protected variables. Those keywords make sense because at times you want variables in a class to which no one outside the class has access to.

Why is that not required in Python?

Zags
  • 37,389
  • 14
  • 105
  • 140
Omnipresent
  • 29,434
  • 47
  • 142
  • 186

15 Answers15

1139

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.

Kirk Strauser
  • 30,189
  • 5
  • 49
  • 65
  • 30
    That makes sense. However, I dont think there is any way in java to access private variables outside the class (except actually changing the source of the class ofcourse). Is there? – Omnipresent Oct 29 '09 at 02:06
  • 2
    Interesting, I come from a PHP background and I'm wondering how this works in practice. Isn't it dangerous for classes to be able to modify what would be private members if the language used was something other than Python? – David Snabel-Caunt Oct 29 '09 at 02:06
  • 3
    Not that I know of, but the point is that you *can* edit the source, or even the compiled bytecode. Nothing can stop you if you're determined enough to mess around with that class's innards. So why expend the effort to prevent it, instead of relying on convention and thin mechanisms to say "don't do that!" And when it comes down to it, no matter how bad of an idea it may usually be, sometimes you really *do* want to fiddle around where you're not supposed to. – Kirk Strauser Oct 29 '09 at 02:10
  • 8
    @David - the presumption is that we're all adults here. Don't break things that you can't fix! In this case, that means that you shouldn't mess around with those private members like __foo or _bar. Again, in practice, that's just not done without an extremely good reason. It might not be theoretically pure, but I've never once seen a real-world situation where it was a problem. – Kirk Strauser Oct 29 '09 at 02:12
  • 3
    +1: We're all adults. The "private" and "protected" keywords are interesting comments, but so is a leading `_` on the variable name. Python is distributed -- and run -- as source. There's no '.class' file to conceal the implementation behind. – S.Lott Oct 29 '09 at 02:24
  • 225
    I tend to prefer the python way, but I don't think the java way is as pointless as you make out. Declaring something private quickly tells someone reading the code something very useful: this field is only ever modified inside this class. – Ned Nov 13 '09 at 09:24
  • 5
    So does __foo in Python, and _bar means that you can but probably shouldn't. – Kirk Strauser Nov 13 '09 at 16:56
  • 85
    @Omnipresent, you can using reflection. – rapadura Mar 22 '11 at 12:49
  • 3
    What matters is that you write good code that solves your problem neatly and efficiently. Anyone who wants to hack your code will ultimately do it. But they probably should have spent the time coding it properly :-) – nialloc Aug 27 '12 at 08:17
  • 11
    probably too little too late, but the access modifiers in java have _very real_ security implications when java code is running within a jvm with a configured SecurityManager. code running when a SecurityManager is configured _cannot_ circumvent the access modifier restrictions. – jtahlborn Aug 12 '13 at 03:43
  • 9
    There's **public**, **private**, and **protected** to enforce access, instead of Python's *_voluntary_* underscore *__convention__*. [Unlike Python, in Ruby](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/). [Visibility in PHP](http://php.net/manual/en/language.oop5.visibility.php) In many **interpreted** languages like _Ruby_, _PHP_ there is a concept of visibility but not in _Python_, in _Python_ they have *culture* – Dmitry Oct 24 '13 at 23:43
  • 4
    @dVaffection if Iain M Banks has taught me anything, it's that the Culture always wins. – Rob Grant Nov 25 '14 at 07:25
  • 6
    Its also worth noting that as a more or less interpreted language, a lot of the considerations a C++ compiler (And I suppose a Java compiler) might have , simply dont exist in python. A private property or method can have various optimizations to speed up access from the local object. It says "Hey compiler, I'm only ever going to be accessed from this object, so dont worry about all the paperwork to get me visible from the outside, heck you can even inline me if thats going to help". In pythons case, its kind of moot. – Shayne Oct 06 '15 at 07:17
  • 143
    Let me get this straight, so Python does not implement public nor private attributes because "its a pretence of security and encourages programmers to be responsible", however the community encourages the use of "_" to denote private variables and methods? Maybe python should definetively have public and private no? Their main purpose is to tell you what API you should use to interact with a class. They serve as a documentation telling you to use these methods and not use those. They are not a "pretence of security", they are API documentation, which can even be used by the IDE to guide you! – PedroD Oct 15 '15 at 11:45
  • 5
    Python *does* definitively have public, semi-public, and private variables: `foo`, `_foo`, and `__foo`. IDEs and other tools support those and call out external references to a class's internals. But again, it doesn't enforce that: if you're determined to escape the sandbox, well, go right ahead but the responsibility of not breaking stuff is on you. – Kirk Strauser Oct 15 '15 at 17:16
  • 6
    Something that doesn't seem to have yet been mentioned specifically is visibility makes it easier to debug: if you have a problem, and that method or variable is out of scope to some code, you know that code didn't call the function that applied an erroneous value to some variable or directly, yet erroneously, modify the variable. With '__' in Python, you can't guarantee it, but it becomes less likely. In other languages (Java, C++), it is certainly helpful (even if it causes consternation to developers who want to add/modify features). – MrMas Nov 18 '15 at 23:08
  • 2
    @Omnipresent: yes you can. Java has the reflection API: http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html "Private" is and has always been a misleading term when it comes to access levels. It's more like "hidden under the hood". Anyone can open the hood, but most people shouldn't. – Arnab Datta Jan 08 '16 at 08:35
  • 14
    Larry Wall expressed the **cultural idea** nicely (for Perl, on the perlmod 5.0 manpage): _"Perl doesn't have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren't invited, not because it has a shotgun."_ Same idea for Python. – Lutz Prechelt Feb 23 '16 at 16:27
  • 1
    You are protecting it from yourself. – Saurabh Apr 08 '16 at 11:48
  • 4
    Reflection isn't exactly something you can do "by accident", and really as far as I know that's the only way to mess with private variables. Its amazing that simultaneously Python encourages us to be "responsible" programmers while talking about how even newbies can code in python! – Aneesh Barthakur Apr 20 '16 at 15:26
  • 5
    @AneeshBarthakur You can't "accidentally" access `AnotherClass.__foo`, either, as you have to calculate its implementation-specific derived name. In CPython 3.5, that would look like `AnotherClass._AnotherClass__foo`. Sure, that's surmountable (as long as you know what implementation your code will be running on!) but it's a giant warning sign that you shouldn't be doing that. – Kirk Strauser Apr 20 '16 at 16:32
  • 1
    You're right.. The few hours between my encounter with this thread and now have educated me a bit on the subject! – Aneesh Barthakur Apr 20 '16 at 18:50
  • @AneeshBarthakur Oh, cool! We're all in this together and learning as we go. :-) – Kirk Strauser Apr 20 '16 at 20:01
  • 57
    This is a good answer and your reasoning is certainly valid, but I disagree with one aspect. The purpose of access modifiers has never been **security**. Rather, they are a means of explicitly demarcating (and to a large degree, enforcing) what parts of a class are considered internal and which are exposed to outside users of that class. Conventions (culture) are certainly a valid alternative to access modifiers, and both methods have their pros and cons, but it is misleading to purpose that language-level access modifiers are intended in any way to be "secure" in the usual sense of the word. – devios1 Jan 04 '17 at 18:43
  • 1
    It is not the 'java way', it is the oop way or the c++ way. – Vassilis Jul 14 '17 at 13:02
  • 3
    Python is OOP and that's not the Python way, so it's not generically "the oop way". – Kirk Strauser Jul 14 '17 at 19:47
  • 2
    We spent years counting on programmers to be careful and not touch things they shouldn't. Guess what, accidents happen. That's why public/private/protected were added to many languages. Just like car alarms (or 'the club'), they will deter a whole class of thieves but not hard-core thieves. Nothing will block them. The purpose of public/private is to get the most bang for the buck, eliminate common classes of mistakes that occur by accident. – Evvo Apr 11 '18 at 23:16
  • 6
    @Evvo you don't "accidentally" type a leading underscore - so whenever you type something like `someobj._attrib` you **know** you are breaking encapsulation. From this very moment you take full responsability for whatever undesirable consequence might happen. – bruno desthuilliers Apr 13 '18 at 06:55
  • 2
    @Bruno -- All kinds of things happen by accident, by people in a hurry, by people who just want a short cut to get onto other things, but accidentally thinking your're typing in a different window. That's the purpose of visibility controls, to avoid this type of accident or misunderstanding. Especially when dealing with 3rd party software. I've spent a very long time as a developer and seen every kind of 'oops' you can imagine. When it comes to discipline and rigor, I trust compilers much more than I trust humans. – Evvo Apr 14 '18 at 14:40
  • 2
    @Evvo well I have been working as professional programmer for 20+ years now and have seen quite a few oops myself, and I definittly DONT trust compilers here - I'd rather trust a good linter and a good unitttest coverage. There's no way to make an idiot-proof language - both Java and Ada failed at it (in a quite epic manner for Ada) - so let's not delude ourselves in thinking that if it's compile it's correct. – bruno desthuilliers Apr 16 '18 at 10:44
  • I got the answer to what I was searching for - there are no access modifiers in Python, but there are "hacks" to make them "near private". However, this answer reeks of a kind of "high horse" attitude, trying to demean Java/C++ (and any other languages that do have these modifiers). As a long time Java developer, deciding to have a go at Python for fun, this answer is surely demoralising :-( – Saurabh Srivastava Jun 11 '18 at 08:59
  • 1
    Hi @SaurabhSrivastava! This wasn't meant to be demoralizing or condescending. I was smiling when I wrote this a decade ago, and I'm smiling today. Welcome to the fun! – Kirk Strauser Jun 11 '18 at 23:47
  • 1
    Its worth noting that private and public isnt really about security. If a bad guy has access to your stuff via code, your already owned. Its more about code hygiene , enforcing encapsulation, and letting the compiler know whether to compile into cheap *local* calls or slightly more expensive method calls. Anything that doesn't belong in the contract, you make private so when your class calls itself via those private calls the compiler can generate faster C style calls for those. Python trusts you to write hygenic code and being an interpreted language, compiler optimisation doesn't count. – Shayne Aug 16 '18 at 12:46
  • When a user types `dir(SomeObject)` and sees an enticingly-named attribute that happens to start with a underscore, there's a good chance they (or I) will try to use it. Usually to read, by why not to set as well? I don't think any number of underscores naturally or obviously makes anything "private" in the traditional sense (and obviousness is usually the best thing about Python). It would be nice if they didn't show up in `dir()` or `help()` etc., that would make them a *lot* more "private". – Demis Oct 01 '18 at 08:02
  • "*In Python, you don't write to other classes' instance or class variables.*" But this would imply the use of setter functions (otherwise you can't ever set anything) which is said to be unpythonic. Isn't it therefore okay to write to class variables as long as they aren't named as though they're private? – Vic May 13 '19 at 06:06
  • 1
    I'm surprised there hasn't been more discussion of those who want to introduce malicious code. This is a real question: Is there no way in Python to prevent a black-hat hacker from accessing your variables and methods and inserting code/data that could deny service, reveal personal (or proprietary company) information? If Python doesn't allow this type of security, should it ever be used for sensitive data? I'm going to research if anyone's asked this question, because I'm going to ask it if no one has. – bballdave025 Aug 20 '19 at 03:11
  • @bballdave025 Given that Python ships as source code, any hackers could literally just edit the code themselves. Those same hackers could modify a .jar file to run their own code, for that matter. I can personally vouch that Python is used for lots of sensitive data handling. – Kirk Strauser Aug 20 '19 at 18:32
  • @Kirl_Strauser , you have made me feel even more secure about using Python with sensitive data - both due to your explanation and your personal vouching. It caps what I found out from [this answer](https://stackoverflow.com/a/57568535/6505499) to my question. – bballdave025 Dec 13 '19 at 00:19
  • 1
    This is a very hypocritical response. At the same time you claim the language drops a "pretence" of security for responsibility reasons, you also say there's a convention to communicate you don't want people to touch your code, which reinforces the importance of encapsulation. – Leonardo Raele Jan 27 '20 at 17:57
  • 2
    @LeonardoRaele I think that you didn't understand this well. What I wrote - over a decade ago - is that Python doesn't treat such things like bulletproof contracts. It takes the same approach to day about typing: although you can say that a function operates on ints, you can pass in a string if you really feel like abusing the system. So instead of hard lines in the sand, the Python approach is to document how you should use the system but not to try very hard to prevent you from doing the opposite, if you really must. – Kirk Strauser Jan 27 '20 at 18:36
  • The main reason for access levels in a class is to isolate the internal business not security. Imagine you are using a third-party class and relay on a variable which is used internally in that class and can be changed any time without any notice! When the language won't support the private members you even can not distinguish the internal purposes variables. – Rman Mar 02 '20 at 04:15
  • 1
    @Rman Fortunately, Python distinguishes between public and private variables. As explained, you _can_ access a private attribute if you absolutely must, but Python doesn’t make it easy for you. – Kirk Strauser Mar 02 '20 at 05:10
  • 1
    I don't put locks on my doors because it's just a "pretence of security". Instead, I encourage the public to be responsible. – loweryjk Oct 29 '20 at 14:45
  • @ArnabDatta in the nice link you posted about accessing private fields and methods in Java the author says "Note: This only works when running the code as a standalone Java application, like you do with unit tests and regular applications. If you try to do this inside a Java Applet, you will need to fiddle around with the SecurityManager." Is there somehting like a security manager also in Python that would prevent accessing a dunderscore variable in an application/API etc. context? – JacoSolari Jun 14 '21 at 08:18
  • what is the soul purpose of encapsulation if the private variable is still accessible in any programming language ? – novice Apr 25 '23 at 10:42
  • Just because you _can_ do something doesn't mean you _should_ do it. Python very clearly says you _shouldn't_ twiddle with another class's mangled names, but if you absolutely must and you're 100% sure of what you're doing, you still can. – Kirk Strauser Apr 26 '23 at 16:21
240

Private variables in Python is more or less a hack: the interpreter intentionally renames the variable.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

Now, if you try to access __var outside the class definition, it will fail:

>>> x = A()
>>> x.__var # this will return error: "A has no attribute __var"

>>> x.printVar() # this gives back 123

But you can easily get away with this:

>>> x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

>>> x._A__var = 456 # you now know the masked name of private variables
>>> x.printVar() # this gives back 456

You probably know that methods in OOP are invoked like this: x.printVar() => A.printVar(x). If A.printVar() can access some field in x, this field can also be accessed outside A.printVar()... After all, functions are created for reusability, and there isn't any special power given to the statements inside.

idmean
  • 14,540
  • 9
  • 54
  • 83
watashiSHUN
  • 9,684
  • 4
  • 36
  • 44
  • 4
    in short, this is not encapsulation – watashiSHUN Sep 26 '15 at 22:11
  • 2
    I wonder if PHP has something similar with its goofy private variables - since private variables don't really make sense in interpreted language - I mean what optimization can it do knowing x variable is private, if it is not compiled? – NoBugs Dec 24 '15 at 05:14
  • 1
    How can we randomize the pattern of private variables? – crisron Feb 07 '16 at 05:29
  • @crisron same question – IanS Feb 17 '16 at 10:47
  • Using ```self.__dic__ = {}``` disallows the use of ```__str__``` method. Is there any work around to use ```__str__``` in this context? – arshovon May 19 '17 at 03:33
  • Actually this is not working. Here is the error: ```AttributeError: 'A' object has no attribute '_A__var1'``` Code: https://gist.github.com/arsho/98db85456f57b92639faedcf7aff045a – arshovon May 19 '17 at 03:40
  • @arsho you are absolutely right, I will try to update if I can find a better solution – watashiSHUN May 19 '17 at 06:03
  • @crisron, you need to use descriptor, here is an [example of renaming attributes](http://intermediatepythonista.com/classes-and-objects-ii-descriptors) – watashiSHUN May 26 '17 at 06:55
  • 11
    @watashiSHUN "in short, this is not encapsulation" => yes it is. Encapsulation is about only using the public API so client code is protected from implementation changes. Naming conventions are a perfectly valid way to tell what is API and what is implementation, and the point is that it just works. – bruno desthuilliers Apr 13 '18 at 07:07
  • 2
    Encapsulation has nothing to do with whether or not you can access a private variable through convoluted methods. Anyone can access the memory directly in C++ which has "private variables". Python can also access "private variables". Big deal. – Mateen Ulhaq Oct 23 '18 at 22:21
  • On the other hand, if you provide `get` and `set` methods for private fields, you can safely claim that *those* are *not* encapsulated! So clearly, encapsulation is a concern of design, not language features. – Mateen Ulhaq Oct 23 '18 at 22:24
37

As correctly mentioned by many of the comments above, let's not forget the main goal of Access Modifiers: To help users of code understand what is supposed to change and what is supposed not to. When you see a private field you don't mess around with it. So it's mostly syntactic sugar which is easily achieved in Python by the _ and __.

Ardavan
  • 1,896
  • 1
  • 13
  • 8
  • 5
    I think this is as important a point as any. When debugging code (I know, I'm a weakling to introduce bugs), know which classes can change a member variable simplifies the debugging process. At least, if the variable is protected by some scope. A similar concept is const functions in C++. I *know* that member variables weren't changed in there and so I don't even look at that method as the potential cause of a bad variable setting. Although it can make subsequent development of class extensions/adding features, limiting the visibility of code makes it easier to debug. – MrMas Nov 18 '15 at 23:01
30

Python does not have any private variables like C++ or Java does. You could access any member variable at any time if wanted, too. However, you don't need private variables in Python, because in Python it is not bad to expose your classes' member variables. If you have the need to encapsulate a member variable, you can do this by using "@property" later on without breaking existing client code.

In Python, the single underscore "_" is used to indicate that a method or variable is not considered as part of the public API of a class and that this part of the API could change between different versions. You can use these methods and variables, but your code could break, if you use a newer version of this class.

The double underscore "__" does not mean a "private variable". You use it to define variables which are "class local" and which can not be easily overridden by subclasses. It mangles the variables name.

For example:

class A(object):
    def __init__(self):
        self.__foobar = None # Will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # Will be automatically mangled to self._B__foobar

self.__foobar's name is automatically mangled to self._A__foobar in class A. In class B it is mangled to self._B__foobar. So every subclass can define its own variable __foobar without overriding its parents variable(s). But nothing prevents you from accessing variables beginning with double underscores. However, name mangling prevents you from calling this variables /methods incidentally.

I strongly recommend you watch Raymond Hettinger's Python's class development toolkit from PyCon 2013, which gives a good example why and how you should use @property and "__"-instance variables (relevant section starts at 37min 16sec).

If you have exposed public variables and you have the need to encapsulate them, then you can use @property. Therefore you can start with the simplest solution possible. You can leave member variables public unless you have a concrete reason to not do so. Here is an example:

class Distance:
    def __init__(self, meter):
        self.meter = meter


d = Distance(1.0)
print(d.meter)
# prints 1.0

class Distance:
    def __init__(self, meter):
        # Customer request: Distances must be stored in millimeters.
        # Public available internals must be changed.
        # This would break client code in C++.
        # This is why you never expose public variables in C++ or Java.
        # However, this is Python.
        self.millimeter = meter * 1000

    # In Python we have @property to the rescue.
    @property
    def meter(self):
        return self.millimeter *0.001

    @meter.setter
    def meter(self, value):
        self.millimeter = value * 1000

d = Distance(1.0)
print(d.meter)
# prints 1.0
Kyle F Hartzenberg
  • 2,567
  • 3
  • 6
  • 24
Hatatister
  • 962
  • 6
  • 11
  • I'm going to check out that talk. Is the `@property` thing part of standard Python, or is it specific to an IDE? – bballdave025 Aug 20 '19 at 06:23
  • Its part of the standard since python 2.6. If you should use an older version, there is still the possibility to use `property` builtin function, which is available since python 2.2 – Hatatister Aug 21 '19 at 20:25
  • 1
    Sorry to mention this 4 years later, but it's bugging me . In your last example, when you're writting the setter, I think you wrote `meter` instead of `value`. – Daniel F. Jul 19 '22 at 23:27
  • You are right. I corrected the error. – Hatatister Jul 20 '22 at 06:32
  • 1
    This is the best answer. Java developers often forget what property and modules are for in Python. – Alex Oct 26 '22 at 08:48
18

There is a variation of private variables in the underscore convention.

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

There are some subtle differences, but for the sake of programming pattern ideological purity, it's good enough.

There are examples out there of @private decorators that more closely implement the concept, but your mileage may vary. Arguably, one could also write a class definition that uses meta.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shayne
  • 1,571
  • 1
  • 16
  • 20
  • 17
    I realize this is pretty late to the party but this link shows up on google when googling the issue. This doesn't tell the whole story. `__x` as a variable inside class `A` is actually rewritten by the compiler to `_A__x`, it's still not fully private and can still be accessed. – Zorf Oct 13 '14 at 23:20
  • 2
    Of course, if I see a variable named `_A__x`, I'm not going to touch it. It could be contagious. I'll run the hell away from it. – Mateen Ulhaq Jan 09 '17 at 09:00
  • 2
    RIght sure its not a *true* private. But the principle reasoning for hard enforced private in C++ and Java (etc) , compiler optimisation, doesn't really exist in Python, so by-convention private is good enough. Python convention generally is that it trusts that you'll behave yourself without supervision. (And its a newbie trap, but you know, just be thoughtful about class design and consumption) – Shayne Aug 20 '19 at 07:08
  • @Shayne You cannot optimise in C++ based on access specifiers. You can access the private members of a class without resorting to C-style casts using just the header definition with some template tricks. See Johannes Schaub's answer to https://stackoverflow.com/questions/424104/can-i-access-private-members-from-outside-the-class-without-using-friends/424990. Access specifiers really are only for you to protect you from yourself. – Chuu Sep 13 '21 at 16:07
  • You absolutely can. Private members can be optimized as straight relative JMP optcodes, whilst public members require vtables because they can be called externally. Yes work arounds exist, but they require that the access come from within the object. – Shayne Sep 27 '21 at 04:35
16

As mentioned earlier, you can indicate that a variable or method is private by prefixing it with an underscore. If you don't feel like this is enough, you can always use the property decorator. Here's an example:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

This way, someone or something that references bar is actually referencing the return value of the bar function rather than the variable itself, and therefore it can be accessed but not changed. However, if someone really wanted to, they could simply use _bar and assign a new value to it. There is no surefire way to prevent someone from accessing variables and methods that you wish to hide, as has been said repeatedly. However, using property is the clearest message you can send that a variable is not to be edited. property can also be used for more complex getter/setter/deleter access paths, as explained here: https://docs.python.org/3/library/functions.html#property

Cleb
  • 25,102
  • 20
  • 116
  • 151
Isaac Saffold
  • 1,116
  • 1
  • 11
  • 20
13

Python has limited support for private identifiers, through a feature that automatically prepends the class name to any identifiers starting with two underscores. This is transparent to the programmer, for the most part, but the net effect is that any variables named this way can be used as private variables.

See here for more on that.

In general, Python's implementation of object orientation is a bit primitive compared to other languages. But I enjoy this, actually. It's a very conceptually simple implementation and fits well with the dynamic style of the language.

Dan Olson
  • 22,849
  • 4
  • 42
  • 56
  • Yep. The beauty is, the metaprogramming abilities of python mean you can actually implement the fancy stuff if you want (And there are libraries that implement @private/@protected/etc decorators and stuff. Hell I even saw a library that imlemented JS style prototype classes for no goddamn sane reason) , but in practice its just not that necessary.. I kind of hate the "python/js/whatever is a lisp" meme because its almost never true, but python does share 'metaprogramming chops combined with simple syntax' with that language – Shayne Aug 20 '19 at 07:26
7

The only time I ever use private variables is when I need to do other things when writing to or reading from the variable and as such I need to force the use of a setter and/or getter.

Again this goes to culture, as already stated. I've been working on projects where reading and writing other classes variables was free-for-all. When one implementation became deprecated it took a lot longer to identify all code paths that used that function. When use of setters and getters was forced, a debug statement could easily be written to identify that the deprecated method had been called and the code path that calls it.

When you are on a project where anyone can write an extension, notifying users about deprecated methods that are to disappear in a few releases hence is vital to keep module breakage at a minimum upon upgrades.

So my answer is; if you and your colleagues maintain a simple code set then protecting class variables is not always necessary. If you are writing an extensible system then it becomes imperative when changes to the core is made that needs to be caught by all extensions using the code.

Bulwersator
  • 1,102
  • 2
  • 12
  • 30
BlueEagle
  • 89
  • 1
  • 1
7

"In java, we have been taught about public/private/protected variables"

"Why is that not required in python?"

For the same reason, it's not required in Java.

You're free to use -- or not use private and protected.

As a Python and Java programmer, I've found that private and protected are very, very important design concepts. But as a practical matter, in tens of thousands of lines of Java and Python, I've never actually used private or protected.

Why not?

Here's my question "protected from whom?"

Other programmers on my team? They have the source. What does protected mean when they can change it?

Other programmers on other teams? They work for the same company. They can -- with a phone call -- get the source.

Clients? It's work-for-hire programming (generally). The clients (generally) own the code.

So, who -- precisely -- am I protecting it from?

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 1
    @Omnipresent: I don't know about wings, but I do know that -- because of Java -- I don't make much use of duck typing. If I did, I might be even more productive in Python. I find that a good inheritance hierarchy (one that would translate to Java) is usually worth the effort in Python. – S.Lott Oct 29 '09 at 10:16
  • 3
    @Porculus: "making it easy for your IDE to know"... What? My IDE is an editor. I'm the designer. I know what the design is about. My IDE is an editor and knows nothing. Who is the mysterious "nobody" who "accidentally using anything else"? Specifically? Who is the person? Why aren't they informed of the right way to use the API? – S.Lott Jul 23 '10 at 00:53
  • 137
    -1: I agree with Porculus. It's not about forbidding access or hiding something, it's about *implicit* API documentation. Developers as well as compilers/interpreter/code-checker easily see which members are recommended to be used and which ones shouldn't get touched (or at least with care). In most cases it would be a horrible mess if all members of a class or module were public. Consider the distinction of private/protected/public members as a service, saying: "Hey, these members are important while those are used internally and probably not useful for you." – Oben Sonne Oct 06 '10 at 20:38
  • 1
    @Oben Sonne: "Implicit API documentation"? What? Do you mean letting people guess what your intent is? How can anyone guess? The public/private/protected seems very poor compared with actual documentation written to support an actual programmer's use cases. – S.Lott Oct 07 '10 at 00:36
  • 7
    @S.Lott: I agree that API docs have higher priority and often are the only way to communicate intended uses of an API. But sometimes member names and visibility (in terms of private/public) sufficiently speak on their own. Also, I see your point that the idea of implicit documentation does not work well in editors w/o API inspection but it is really helpful in IDE's with code completion. Assuming you've read the API docs already some time ago it helps you to remember how to use a class. Things wouldn't work that smart if there were no distinction between private and public members. – Oben Sonne Oct 14 '10 at 20:33
  • 1
    @Oben Sonne: "Things wouldn't work that smart if there were no distinction between private and public members"? Things? What things? "IDE's with code completion"? Is that the thing which wouldn't work smart? Please read http://www.amazon.com/Large-Scale-Software-Design-John-Lakos/dp/0201633620. Public/private/protected conflate too many things to be actually useful. The API documentation often conveys more -- and more useful -- information that `private`. `private` is simply too little information to be of any real value. – S.Lott Oct 14 '10 at 20:57
  • 24
    Late to the discussion, but everything Porculus and Oben are requesting here is handled perfectly adequately by the "prefix it with an underscore" convention (and without the harm that compiler enforcement of that convention can cause) – ncoghlan Mar 02 '11 at 15:16
  • 2
    @ncoghlan What harm does compiler enforcement cause? – hiwaylon Feb 20 '12 at 17:06
  • 1
    @everybody else See Gamma, E., et al., Design Patterns (1995), p11 and p13. – hiwaylon Feb 20 '12 at 17:21
  • 5
    @hiwaylon: Absolutely true. Totally agree. Encapsulation is a design feature. Privacy doesn't help make a design encapsulated. It only provides compiler support to prevent folks from using attributes they shouldn't. Programming to the interface is a matter of having a defined interface and documenting it. Private is just compiler support to help folks who can't read the documentation or refuse to follow it. – S.Lott Feb 20 '12 at 18:26
  • 2
    @hiwaylon Encapsulation by convention means you can break encapsulation if you have a good reason (such as injecting additional logging to find the source of bad updates to application state). With compiler level enforcement you simply can't do a lot of things that are very useful in dealing with maintaining and testing real world software (look at design patterns for Java & C++: many of them are about writing a lot of extra code to give you some additional extension points). – ncoghlan Feb 23 '12 at 04:13
  • 4
    @hiwaylon It's a "consenting adults" approach to API design - the leading underscore says "you're on your own if you start messing with this, but the language isn't going to stop you if you think it's necessary". Enforcement, on the other hand, puts the original API designer in the position of saying "thou shalt not use my API in ways I did not plan for up front. Even if you're willing to assume the associated risks, the compiler simply won't let you." – ncoghlan Feb 23 '12 at 04:14
  • 9
    @ncoghlan These points are made all over the internet and in Python publications galore. Doesn't make them scripture. Compiler enforcement of an interface, strong data encapsulation and typing are considered by many to be great benefits. "Privacy doesn't help make a design encapsulated." Agree to disagree. "Private is just ... to help folks who can't read the documentation or refuse to follow it." Again, silly. As we all can agree, there are benefits in both high level, loosely typed languages and low level, strongly typed languages. They are all tools in the toolbox! – hiwaylon Feb 25 '12 at 15:32
  • 4
    @hiwaylon: If you insist on conflating encapsulation -- a design technique -- with privacy -- an Implementation technique -- I can see why you're claiming that privacy is magically essential. Consider a C++ programmer who simply doesn't use `private`. Are you saying that a well-encapsulated, good design magically fails to show good encapsulation because failure to use `private`? If so, then `friend` declarations, which selectively remove privacy, would make the design magically "not encapsulated". Even if well-controlled? I don't buy `private` == good at all. – S.Lott Feb 25 '12 at 18:47
  • 4
    Direct access to public data is a violation of encapsulation. While the underscore convention helps communicate intent, the existence of a `private` keyword in a language is certainly not a bad thing. – hiwaylon Aug 27 '12 at 15:29
  • 1
    Couldn't we effectively implement private, public, protected by clever metaclasses? – gerrit Mar 20 '13 at 23:28
  • 3
    @S.Lott - While I semi-agree, in Java leaving out the `public`/`private` does **NOT** mean "whatever goes". It gives the member default visibility, meaning that it's visible within its package but *not* from anywhere else (including subpackages). You *do* have to use visibility for functionality in most cases. – Qix - MONICA WAS MISTREATED Jul 08 '13 at 20:47
  • 3
    I used to think that private public was a bit silly, but after getting into using classes properly, where you may have significant amounts of very small functions on a class, you want to be able to add methods that are only designated to be used from other methods in that class. The point is, if you know that method will only ever make sense to be called from a different method on the same class, then make it private, and you don't think about it if you are outside. – Chris Barry Aug 25 '13 at 19:00
  • 43
    @S.Lott I'm not a python guy, so I won't comment from that perspective. However as a java developer this is truly horrifying advice. -1 – dbyrne Jun 06 '14 at 14:24
  • 3
    Protecting from my bonehead mistakes, maybe? I agree with the notion that access modifiers help you reason about the code. They provide compile time notification of what is expected by the person who wrote the library (assuming they knew what they were doing). I love Python, but saying you have never used `private` or `protected` in your entire career seems overly stubborn. There is value in communicating your intentions to the compiler in the absence of cultural conventions like in Python. In most languages that support them, others expect you to leverage them to communicate your intentions. – jpmc26 Jul 02 '14 at 00:13
  • 2
    Isn't it all about enforcement? In Java, the compiler enforces the intention of the writer. In Python, the lack of a working program indicates the Python interpreter enforces the intention of the write. OTOH, using a Java class at runtime incorrectly indicates one did not read the documentation or understand the design. In Python it indicates the same. It depends on what you want to make the other coder(s) use, and how you want them to discover how to use it. All would use documentation. Java would make you read at compile time (or after). Python when the program blows up. – johnny Dec 29 '14 at 17:50
  • 3
    Agree with S.Lott. If the whole point is implicit indication of usage, Python solves it with the underscore prefix, and since there is no other point, as we've concluded, Java's private/public is an unnecessary complication. – Russia Must Remove Putin Feb 06 '15 at 16:57
  • 2
    Private and protected variables enforce good design practices. We are all humans, and we all can feel lazy or tired at times. Many people can't force themselves to stop smoking, or to start exercising, even though they know what's best for them. Similarly, a lot of people would be tempted to use private variables if there is such no obstacle to doing so. Declaring something private is making a commitment that you're going to live up to. The advantage is that you can almost perfectly encapsulate a piece of code, polish it and feel secure about it. This security never happens in python. – Sergey Orshanskiy Apr 14 '15 at 05:44
  • 1
    Don't agree, it enhance readability and help other programmer know the method should use or not even if they could change. – Sing Jan 13 '17 at 07:39
  • 14
    Wow. You miss the point completely, you give a very bad piece of advice, you insult anyone who disagrees with you on this point, but you still get badges and more than 1000 reputation points for this "answer". – Eric Duminil Jan 19 '17 at 14:46
  • +1 But finally @S.Lott has posted about 2500 posts and 've earned about 20000 reputations on the tag 'python'. Language is just a language, it may have some parts you won't agree on forever, but does it matter to be a good programmer? The answer is apparent. – NeoZoom.lua Apr 23 '18 at 07:56
  • Not to mention about design patterns, which he also 've earned lots of badge on Software Engineering SE site. – NeoZoom.lua Apr 23 '18 at 08:10
  • Ok then, your points about `protected` is demagogy but ok. So, what about `private`? The intrigue!: will `private` in your interpretation will become a soldier of lowest rank? Or you will claim programmer will be forced to own a var/method, but you are a communist and are against private property (pun unintended) for the means of production (and vars/methods are the means of production obviously)? – jungle_mole Aug 15 '19 at 07:42
  • I've worked with clients who handle highly sensitive and personal information. For me, the private and protected keywords have been essential to prevent black-hat hackers from maliciously inserting code or data to exposed methods. From what I'm reading - and I'm happy if someone tells me I'm not understanding it right - Python doesn't allow you to prevent someone with malicious intent from accessing your sensitive information. It seems that the class and instance variables and functions don't really have a good security method. (to be continued...) – bballdave025 Aug 20 '19 at 03:19
  • (... cont'd) Q: "protected from whom?" A: "from malicious black-hat hackers - access variables and functions -> deny service, access sensitive info..." It seems the `A._no_touch = 5` approach would cause such a malicious coder to laugh at my "please don't touch this". My `A.__get_SSN(self)` seems to be just wishful hoping that black hat doesn't know [Zorf's trick](https://stackoverflow.com/questions/1641219#comment41361223_25614597). I want to be told how I'm totally missing things. Should one not code for sensitive info in Python? I really don't know, but I'd like to know. – bballdave025 Aug 20 '19 at 04:06
  • Its worth noting that in compiled languages Private/Public actually have performance implications as they determine whether to route calls directly (ie private self call) or via call table indirection (looking up a method on a foreign class, possibly taking a few laps of the class heirachy and then calling it) – Shayne Aug 20 '19 at 07:11
  • @bballdave025 Protection levels are not about security. I assure you if a black hat has memory access neither hell nor high water is going to hide class properties from him. Its about documenting for the coder (and compiler!) the audience for a method.. Is it for internal use to the class, or is it 'published' to other classes to use. If you want secure fields, thats a topic well out of scope for method and property visibility. – Shayne Aug 20 '19 at 07:14
  • @Shayne, that's a simple statement, but it helps me understand where I'm getting off course in my thoughts. If I understand what you're saying, `public`, `private`, `protected`, and underscores aren't there for computer security, they're to let those who will work with your code know what belongs to which class. Does that sound right? I always thought those keywords were about computer security. It's nice to learn their real use. – bballdave025 Aug 20 '19 at 07:17
  • No Public, Protected and Private have absolutely nothing to do with security. They are about audience for elements of a classes contract. If you are relying on them for security, you're going to be in for a bad time I'm afraid. The compiler does absolutely nothing to keep them safe from bad actors because its just not what those language features are for. – Shayne Aug 20 '19 at 07:21
  • Thanks. Luckily, I don't work in security. I'm a physicist who learned to code, especially in grad school, loved it, and moved to research and development in the computer world. I always like to fill in the gaps left by my education. Thanks for taking the time to explain that to me. – bballdave025 Aug 20 '19 at 07:36
  • No problems buddy, thats what SOs for :) – Shayne Aug 20 '19 at 08:32
  • (Referenced in [a meta post](https://meta.stackexchange.com/questions/50388/what-is-the-most-controversial-answer-on-stack-overflow/383483#383483).) – Peter Mortensen Nov 04 '22 at 13:40
7

In Python 3, if you just want to "encapsulate" the class attributes, like in Java, you can just do the same thing like this:

class Simple:
    def __init__(self, str):
        print("inside the simple constructor")
        self.__s = str

    def show(self):
        print(self.__s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

To instantiate this do:

ss = Simple("lol")
ss.show()

Note that: print(ss.__s) will throw an error.

In practice, Python 3 will obfuscate the global attribute name. It is turning this like a "private" attribute, like in Java. The attribute's name is still global, but in an inaccessible way, like a private attribute in other languages.

But don't be afraid of it. It doesn't matter. It does the job too. ;)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ferrarezi
  • 801
  • 10
  • 12
5

Private and protected concepts are very important. But Python is just a tool for prototyping and rapid development with restricted resources available for development, and that is why some of the protection levels are not so strictly followed in Python. You can use "__" in a class member. It works properly, but it does not look good enough. Each access to such field contains these characters.

Also, you can notice that the Python OOP concept is not perfect. Smalltalk or Ruby are much closer to a pure OOP concept. Even C# or Java are closer.

Python is a very good tool. But it is a simplified OOP language. Syntactically and conceptually simplified. The main goal of Python's existence is to bring to developers the possibility to write easy readable code with a high abstraction level in a very fast manner.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user711294
  • 185
  • 1
  • 1
  • 3
    The rearson Private and Protected are important is that in statically compiled languages the compiler can create diirect calls to the private method, but must rely on a lookup table for public methods. Thiis simply isnt an issue with dynamic languages. Finally languages like C++ there are implications for inheritance and method resolution. Python and Ruby have very similar implementatiions of OO, so the comparison is meaningless. Smalltalk actually has no notion of public/private messages. Your free to add private as a category, but its purely advisory. – Shayne Feb 24 '17 at 05:21
  • To further my assertion. Frorm a codiing hygiene point of view, yes they are important for encapsulation, but its not *necessary* for it, and so the the @private (etc) decorators are more advisory than anything, but as private/public adds nothing useful to optimization in a non static language, its not implemented at a deep level like it would in a compiled language like java or c – Shayne Feb 27 '17 at 02:35
1

Here's how I handle Python 3 class fields:

class MyClass:
    def __init__(self, public_read_variable, private_variable):
        self.public_read_variable_ = public_read_variable
        self.__private_variable = private_variable

I access the __private_variable with two underscores only inside MyClass methods.

I do read access of the public_read_variable_ with one underscore outside the class, but never modify the variable:

my_class = MyClass("public", "private")
print(my_class.public_read_variable_) # OK
my_class.public_read_variable_ = 'another value' # NOT OK, don't do that.
mercury0114
  • 1,341
  • 2
  • 15
  • 29
0

About sources (to change the access rights and thus bypass language encapsulation like Java or C++):

You don't always have the sources and even if you do, the sources are managed by a system that only allows certain programmers to access a source (in a professional context). Often, every programmer is responsible for certain classes and therefore knows what he can and cannot do. The source manager also locks the sources being modified and of course, manages the access rights of programmers.

So I trust more in software than in human, by experience. So convention is good, but multiple protections are better, like access management (real private variable) + sources management.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alan Allen
  • 71
  • 5
0

So I’m new to Python but I have a background in C# and JavaScript. Python feels like a mix of the two in terms of features. JavaScript also struggles in this area and the way around it here, is to create a closure. This prevents access to data you don’t want to expose by returning a different object.

def print_msg(msg):
    # This is the outer enclosing function

    def printer():
        # This is the nested function
        print(msg)

    return printer  # returns the nested function


# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()

https://www.programiz.com/python-programming/closure

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#emulating_private_methods_with_closures

julemand101
  • 28,470
  • 5
  • 52
  • 48
Simon Stanford
  • 353
  • 3
  • 10
  • 2
    I'm not sure how this relates to the question... It is about private attributes ***in a class***, not closure in functions... – Tomerikoo Dec 27 '21 at 09:35
  • 3
    **Don't do this in Python**. In Python, you simply use a leading underscore to signal that an attribute is "private", there *are no access modifiers*. Don't replace your classes with closures. – juanpa.arrivillaga Dec 27 '21 at 09:42
0

I have been thinking about private class attributes and methods (named members in further reading) since I have started to develop a package that I want to publish. The thought behind it were never to make it impossible to overwrite these members, but to have a warning for those who touch them. I came up with a few solutions that might help. The first solution is used in one of my favorite Python books, Fluent Python.


Upsides of technique 1:

  • It is unlikely to be overwritten by accident.
  • It is easily understood and implemented.
  • Its easier to handle than leading double underscore for instance attributes.

*In the book the hash-symbol was used, but you could use integer converted to strings as well. In Python it is forbidden to use klass.1

class Technique1:

    def __init__(self, name, value):
        setattr(self, f'private#{name}', value)
        setattr(self, f'1{name}', value)

Downsides of technique 1:

  • Methods are not easily protected with this technique though. It is possible.
  • Attribute lookups are just possible via getattr
  • Still no warning to the user

Another solution I came across was to write __setattr__. Pros:

  • It is easily implemented and understood
  • It works with methods
  • Lookup is not affected
  • The user gets a warning or error
class Demonstration:

    def __init__(self):
        self.a = 1

    def method(self):
        return None

    def __setattr__(self, name, value):
        if not getattr(self, name, None):
            super().__setattr__(name, value)
        else:
            raise ValueError(f'Already reserved name: {name}')

d = Demonstration()
#d.a = 2
d.method = None

Cons:

  • You can still overwrite the class
  • To have variables not just constants, you need to map allowed input.
  • Subclasses can still overwrite methods

To prevent subclasses from overwriting methods you can use __init_subclass__:

class Demonstration:
    __protected = ['method']

    def method(self):
        return None

    def __init_subclass__(cls):
        protected_methods = Demonstration.__protected
        subclass_methods = dir(cls)
        for i in protected_methods:
            p = getattr(Demonstration,i)
            j = getattr(cls, i)
            if not p is j:
                raise ValueError(f'Protected method "{i}" was touched')

You see, there are ways to protect your class members, but it isn't any guarantee that users don't overwrite them anyway. This should just give you some ideas. In the end, you could also use a meta class, but this might open up new dangers to encounter. The techniques used here are also very simple minded and you should definitely take a look at the documentation, you can find useful feature to this technique and customize them to your need.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thingamabobs
  • 7,274
  • 5
  • 21
  • 54