Python Access Restrictions private public details
- 2020-12-16 06:01:40
- OfStack
1. Knowledge
In a module, we may define many functions and variables. But there are functions and variables that we want to be able to use for others, and there are functions and variables that we want to use only within the module.
We can do this by defining whether the function, the variable, is public or private.
In Python, this is done with the underscore "_" prefix.
It should not be directly referenced, only accessible internally, not externally.
The state inside the object cannot be changed at will, so the code is more robust, protected by access restrictions.
2. Give examples
Inside the Class class, you can have properties and methods. The external code can manipulate the data by calling the method of the instance variable directly, hiding the internal complex logic. However, the external code is still free to modify the properties of an instance. Such as:
>>>b.score
99
>>>b.score = 59
>>>b.score
59
If you want to keep the internal property from being accessed externally, you can make the property's name private by putting the underscore "__" in front of it, as follows:
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
An attempt to access the property externally will report an error because the private variable cannot be accessed externally.
>>> bart = Student('Bart Simpson', 98)
>>> bart.__name # Private variable: cannot be accessed externally
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__name'
But what if the external code wants to get name and score?
Add methods to the Student class to get attributes: get_name() and get_score(), as follows:
class Student(object):
...
def get_name(self):
return self.__name
def get_score(self):
return self.__score
What if the external code modifies score? You can add Settings to the Student class: set_score() :
...
def set_score(self, score):
# Avoid passing in invalid parameters
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')
Is a private instance variable that starts with a double underscore 1 must not be accessed externally? Not really.
___, 62EN cannot be accessed directly because the Python interpreter changes the ___ 64en variable to _Student___ name, so the ___ variable can still be accessed with _StudentES68en.
>>> bart = Student('Bart Simpson', 98)
>>> bart.get_name()
'Bart Simpson'
>>> bart.__name = 'New Name' # to bart The addition of __name variable
>>> bart.__name # ! with class The inside of the __name Variables are not 1 A variable!
'New Name'
>>> bart.get_name() # get_name() Internal return self.__name (_Student__name)
'Bart Simpson'
On the surface, the external code "succeeds" sets the ___ 73en variable, but in fact the ___ 74en variable and the ___ 76en variable within class are not a single variable! The internal ___ variable has been automatically changed by the Python interpreter to _StudentES80en, and the external code adds one more ___ to bart.
Therefore, python does not have a method to completely restrict access to private functions or variables, so it is not "cannot be referenced directly", and it is customary to not refer to private functions or variables. What about their use?
Such as:
def _private_1 (name):
return 'hello,%s ' % name
def _private_2 (name):
return 'hi , %s ' % name
def greeting(name):
if len(name) > 3:
return _private_1 (name)
else:
return _private_2 (name)
Expose the greeting() function in the module and hide the internal logic with the private function. This way, calling the greeting() function does not have to worry about the details of the internal private function.
This is a very useful approach to code encapsulation and abstraction: all functions that need not be referenced externally are defined as private, and only those that need to be referenced externally are defined as public.
3. Complete code
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_score(self, score):
# Avoid passing in invalid parameters
if 0 <= score <= 100:
self.__score = score
else:
raise ValueError('bad score')
def _private_1 (name):
return 'hello,%s ' % name
def _private_2 (name):
return 'hi , %s ' % name
def greeting(name):
if len(name) > 3:
return _private_1 (name)
else:
return _private_2 (name)