Reputation: 73
I found this code:
public="a" # is a public variable
_protected="b" # is a protected variable
__private="c" # is a private variable
Example of how it's used:
class c1:
def __init__(self,a,b,c):
self.public=a
self._protected=b
self.__private=c
v=c1("A","B","C")
print(v.public)
v._protected="Be" # !??? I can access a protected variable
print(v._protected)
print(v.__private) # !??? AttributeError: 'c1' object has no attribute '__private'
Why can I access a variable that was supposed to be a protected variable!?
Upvotes: 3
Views: 2238
Reputation: 522451
No, Python does not have access modifiers which outright prevent access. But then again, most languages don't. Even languages which sport protected
and private
keywords usually have some way through introspection or such to get at the value anyway in ways which "should not be allowed."
Access modifiers are, one way or another, just a hint as to how the property is supposed to be used.
Python's philosophy is to assume that everyone contributing code is a responsible adult, and that a hint in the form of one or two underscores is perfectly enough to prevent "unauthorised access" to a property. If it starts with an underscore, you probably shouldn't mess with it.
Upvotes: 4
Reputation: 6341
Python doesn't have modifiers like private
, protected
, public
. You can emulate their behavior with __getattr__
and __getattribute__
, but it's not a Pythonic way to write programs.
Using single underscore _
is a convention, so when you see an attribute or method starting with one underscore, consider that library developer didn't expect it to be part of public API. Also when executing from module import *
Python interpreter doesn't import names starting with _
, though there're ways to modify this behavior.
Using double underscore __
is not just a convention, it leads to "name-mangling" by interpreter - adding class name in front of attribute, so i.e.:
class Klass():
def __like_private():
print("Hey!")
will make _Klass__like_private
.
You won't be able to access __like_private
directly as defined, though you still will be able to get to it knowing how names are composed by using _Klass__like_private()
in subclasses for example or in module:
Klass.__like_private()
will give you an error.
Klass._Klass__like_private()
will print Hey!
.
Upvotes: 2
Reputation: 31682
You could acess your protected variable as:
print(v._c1__private)
'C'
Upvotes: 1