Python object-oriented encapsulation

Posted by GundamSV7 on Sun, 06 Mar 2022 06:09:38 +0100

A concept of encapsulation

In fact, packaging is everywhere in our life, such as televisions, computers, mobile phones and other items. Usually, we can only see the external shape and use the functions provided by them, but we can't see the complex hardware composition inside. These are encapsulated and can't be seen by us. We can avoid some "special" operations so that it can't work normally. Programming comes from life. There are also encapsulation operations on objects in python, so that it only provides a fixed access mode, and cannot access its internal private properties and private methods. Encapsulation in python generally refers to the encapsulation of class attributes and class methods, that is, the privatization of class attributes and class methods, as described in the following summary.

II_ And__ Privatization of properties and methods

1. Single underline_

When properties and methods in a class_ When a single underscore begins, it means that this class of protected variables and methods do not want to be accessed externally according to the coding convention. But if you want to make an interview, you won't report an error. as follows

class A():
    #_  Declarations are protected properties and protected methods
    _name = 'Zhang San'
    def __init__(self):
        self._age = 23

    def _method(self):
        print("My name is{},this year{}year".format(self._name, self._age))

if __name__ == '__main__':
    a = A()
    #Print dir of class A
    print(a.__dir__())
    #Access protection variables and protection methods
    print(a._name)
    a._method()

Output results

>>>
['_age', '__module__', '_name', '__init__', '_method', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
Zhang San
 My name is Zhang San,He is 23 years old

It can be seen that_ The properties and methods starting with a single underscore are actually accessible outside the class, but according to the Convention, when we see such properties and methods, we should not access them outside.

2. Double underline__

Although the above properties and methods starting with a single underscore are protected, they can still be accessed externally. And when you see double underlined__ When using the properties and methods at the beginning, please remember that they are private properties and private methods of the class. Methods that routinely access class properties and methods outside the class and in subclasses cannot be accessed or modified, as shown below

class B():
    #__  The declaration is privatized
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        #Private method
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def fun(self):
        #public Method 
        print("this is a public method")
 
 if __name__ == '__main__':
    b = B()
    #Print dir of class B
    print(b.__dir__())
    #Access private properties and private methods of class B
    b.fun()
    print(b.__name, b.__age, b.__luange)
    b.__method()

Output results

>>>
['_B__age', '_B__luange', '__module__', '_B__name', '__init__', '_B__method', 'fun', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
this is a public method
Traceback (most recent call last):
  File "C:/Users/admin/python-learning/python Learning documents/python Basics/python Class encapsulation.py", line 56, in <module>
    print(b.__name, b.__age, b.__luange)
AttributeError: 'B' object has no attribute '__name'

It can be seen from the results that the public method fun() of class B is normally output, but when we access the private attribute name, we throw an error: Class B has no name attribute. When the above single underline is used, we print the dir of class A. We can see that the name attribute and method method of class A are as follows in dir

Above, we also printed the private properties and private methods of class B, as follows

You can see that private properties and private methods have become_ B__ Properties and_ B__ So in our form__ It is an error to access in the form of name or name. In fact, if we use the class name ()_ Class name__ Property (instance property) or class name_ Class name__ Attribute (class attribute) will be accessed successfully. as follows

class B():
    #__  The declaration is privatized
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        #Private method
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def fun(self):
        #public Method 
        print("this is a public method")

if __name__ == '__main__':
    b = B()
    #Print dir of class B
    print(b.__dir__())
    #Access private properties and private methods of class B
    b.fun()
    print(B._B__name, b._B__age, b._B__luange)
    b._B__method()

give the result as follows

>>>
['_B__age', '_B__luange', '__module__', '_B__name', '__init__', '_B__method', 'fun', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
this is a public method
 Zhang San 23 python
 My name is Zhang San,He is 23 years old,I like it python. 

3. Access the private properties and private methods of the parent class in the subclass

  • Subclasses cannot access private properties and private methods of the parent class
class B():
    #__  The declaration is privatized
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        #Private method
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def fun(self):
        #public Method 
        print("this is a public method")

class C(B):

    def __init__(self):
        super().__init__()

    def fun1(self):
        #Access private properties and private methods of parent class B
        print(self.__name, self.__age, self.__luange)
        self.__method()

if __name__ == '__main__':
    c = C()
    c.fun1()

Output results

>>>
AttributeError: 'C' object has no attribute '_C__name'
AttributeError: 'C' object has no attribute '_C__method'

It can be seen that subclasses cannot access the private properties and methods of the parent class.

  • When the properties and methods of a subclass have the same name as the private properties and methods of the parent class, the private properties and methods of the parent class will not be overwritten.
class B():
    #__  The declaration is privatized
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        #Private method
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def fun(self):
        #public Method 
        print("this is a public method")

class C(B):
    __name = 'Li Si'
    def __init__(self):
        super().__init__()
        self.__age = 24
        self.__luange = 'C++'

    def fun1(self):
        #Access private properties and private methods of parent class B
        print(self.__name, self.__age, self.__luange)
        self.__method()

    def __method(self):
        #The private method of class C has the same name as the parent method, but does not override the parent method
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))
        #Call the private method of the parent class
        B()._B__method()

if __name__ == '__main__':
    c = C()
    #Accessing private methods of class C
    c._C__method()

give the result as follows

>>>
My name is Li Si,He is 24 years old,I like it C++. 
My name is Zhang San,He is 23 years old,I like it python. 

As you can see, subclass C does not override the of parent class B__ method() method. Why? Let's print the dir of B and C as follows

>>>
['_B__age', '_B__luange', '_C__age', '_C__luange', 'fun1',
 '_C__method', '__doc__', '_B__name', '_B__method', '_C__name', ...]

It can be seen that in dir of class C, the private attributes and private methods of parent class B are_ B__ Properties (Methods) exist. Class II C's own private properties and private methods are based on_ C__ If the property (method) exists, that is, the private property and private method of the class will_ Class name_ The form of attribute (method) exists in dir, so when the attribute and method of the subclass have the same name as the private attribute and private method of the parent class, it will not be overwritten.

Third, access and modify the private properties and methods of the class

Class can encapsulate and protect properties and methods by privatizing them. But what happens when the outside world needs access and change? Just like TV sets, computers also provide fixed interfaces.
Above, although we can pass the class name ()_ Class name__ Property (instance property) or class name_ Class name__ Property (class property) to access the private properties and private methods of a class, but this violates the programming specification and is not supported, just as it will not disassemble the TV to operate on it.

There are generally two methods to access and modify private properties and private methods of a class, as follows

1. User defined public method

class D():
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def get_value(self):
        return self.__name, self.__age, self.__luange

    def get_method(self):
        self.__method()

    def set_value(self, name, age, luange):
        self.__name, self.__age, self.__luange = name, age, luange

if __name__ == '__main__':
    d = D()
    #Through get_ The value method accesses private properties
    print(d.get_value())
    #Through get_ The method method accesses private methods
    print('=' * 30)
    d.get_method()
    #Through set_ The value method modifies private properties
    print('='*30)
    print(d.get_value())
    d.set_value('Wang Er Ma Zi', 25, 'Linux')
    print(d.get_value())
    d.get_method()

Output results

>>>
('Zhang San', 23, 'python')
==============================
My name is Zhang San,He is 23 years old,I like it python. 
==============================
('Zhang San', 23, 'python')
('Wang Er Ma Zi', 25, 'Linux')
My name is Wang ermazi,He is 25 years old,I like it Linux. 

As you can see, we use the custom get_value(),get_method() and set_ The value () method implements the access and modification of private properties and private methods.

2. property

property generally has two functions, as follows

  • As a decorator, @ property turns a class's method into a read-only class property
  • Property re implements the getter and setter methods of a property

Let's take a look at the following class E, as follows

class E():
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    def get_value(self):
        return self.__name

    def set_value(self, name):
        self.__name = name

    getValue = property(get_value, set_value)

    @property
    def get_method(self):
        self.__method()

if __name__ == '__main__':
    e = E()
    #visit
    print(e.getValue)
    e.get_method
    #modify
    e.getValue = 'WangTwo '
    print(e.getValue)

result

>>>
Zhang San
 My name is Zhang San,He is 23 years old,I like it python. 
WangTwo 

As you can see, we will get_value and set_ After the value method passes in the property, the class method is converted into a class property and assigned to the getValue variable. At this time, e.getValue is read-only, that is, get_value method, e.value = 'Wang Er' is modification, i.e. get_value method. Same. Get through @ property_ Method method becomes an attribute.

The following property re implements the getter and setter methods of a property, which is different from the above writing method and more commonly used than the above.

class E():
    __name = 'Zhang San'

    def __init__(self):
        self.__age = 23
        self.__luange = 'python'

    def __method(self):
        print("My name is{},this year{}year,I like it{}. ".format(self.__name, self.__age, self.__luange))

    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self, name):
        self.__name = name

if __name__ == '__main__':
    e = E()
    #visit
    print(e.name)
    #modify
    print("Before modification:", e.name)
    e.name = 'Lao Wang next door'
    print("After modification:", e.name)

Output results

>>>
Zhang San
 Before modification: Zhang San
 After modification: Lao Wang next door

Above is the first method to decorate the propert decorator with the name method, then call the decorated setter method, then we can modify the private property.

Topics: Python encapsulation property