Verde
Verde

Reputation: 73

Does Python have access modifiers?

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

Answers (3)

deceze
deceze

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

Nikita
Nikita

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

Anton Protopopov
Anton Protopopov

Reputation: 31682

You could acess your protected variable as:

print(v._c1__private)
'C'

Upvotes: 1

Related Questions