Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!?

like image 259
Verde Avatar asked Aug 13 '26 08:08

Verde


2 Answers

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.

like image 176
deceze Avatar answered Aug 14 '26 21:08

deceze


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

like image 24
Nikita Avatar answered Aug 14 '26 23:08

Nikita



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!