SoFunction
Updated on 2024-11-12

Encapsulation in Python Object-Oriented Details

I Concept of Encapsulation

Encapsulation is actually everywhere in our lives, such as TV sets, computers, cell phones and other items. We usually can only see its external shape, and the use of the functions they provide, and can not see the internal complexity of the hardware composition, these are encapsulated, can not let us see, to avoid some of our "special" operation, so that it can not work properly. Programming comes from life. InpythonIn python, encapsulation generally refers to the encapsulation of class attributes and methods, i.e., the privatization of class attributes and the privatization of class methods, as described in the following summary.

II __ and __ Privatization of attributes and methods

1. Single underline _

When properties and methods in a class begin with a _ single underscore, it means that they are protected variables and protected methods of the class, and according to coding conventions, are not intended to be accessed externally. However, if you want to access them, you will not report an error.

Below:

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{},last year{}year (of crop harvests)".format(self._name, self._age))

if __name__ == '__main__':
    a = A()
    # Print the dir of class A
    print(a.__dir__())
    # Access to protected variables and protected 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__']
John Doe
My name is Zhang San, I'm 23 years old.

As you can see, properties and methods that begin with a _ single underscore are actually accessible outside the class, but by convention, when we see such properties and methods, we should not access them externally.

2. Double underlining ___

The properties and methods beginning with a single underscore above are protected, but they are still accessible from the outside. When you see attributes and methods that begin with a double underscore __, remember that they are private attributes and methods of the class, and cannot be accessed outside the class or subclasses in the normal way of accessing class attributes and methods, nor can they be modified, as follows

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

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

    def __method(self):
        # Private methods
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))

    def fun(self):
        # Publicly owned methods
        print("this is a public method")
 
 if __name__ == '__main__':
    b = B()
    # Print the dir of class B
    print(b.__dir__())
    # Access to private properties and private methods of class B
    ()
    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/pythonLearning documents/pythoninfrastructural/pythonclass encapsulation.py", line 56, in <module>
    print(b.__name, b.__age, b.__luange)
AttributeError: 'B' object has no attribute '__name'

As you can see from the results, accessing the public methods of class Bfun()is output normally, but when we access the private attribute name, it throws an error: class B does not have a name attribute. When we print the dir of class A with the single underscore above, we can see that class A'snameattributes andmethodThe method inside the dir looks like this

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

You can see that the private attributes and private methods have become the form of __B__ attributes and __B__ methods, so we access them in the form of __ name or name above is an error, in fact, if we access them in the form of class name (). _ class name__ attribute (instance attribute) or class name. __ class name__ attribute (instance attribute) or class name. As follows

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

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

    def __method(self):
        # Private methods
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))

    def fun(self):
        # Publicly owned methods
        print("this is a public method")

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

The results are 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, I'm 23 years old and I love python.

3. access to private attributes and private methods of the parent class in the child class

Subclasses cannot access private properties and private methods of the parent class:

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

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

    def __method(self):
        # Private methods
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))

    def fun(self):
        # Publicly owned methods
        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'

You can see that subclasses are also unable to access the private properties and private methods of the parent class.

Attributes and methods in subclasses do not override the private attributes and methods of the parent class when they have the same name as the private attributes and methods of the parent class.

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

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

    def __method(self):
        # Private methods
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))

    def fun(self):
        # Publicly owned methods
        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):
        # Private methods of class C with the same name as the parent method, but without overriding the parent method
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))
        # Call private methods of the parent class
        B()._B__method()

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

The results are as follows:

>>>
My name is Li Si,I am 24 years old,I like C++.
My name is Zhang San, I'm 23 years old, and I love python.

You can see that subclass C does not override the __method() method of parent class B. Why is this? Let's print the dir of B and C.Below:

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

You can see that in the dir of class C, the private attributes and private methods of the parent class B exist as __B__ attributes (methods), and the private attributes and private methods of the second class C itself exist as __C__ attributes (methods), i.e., the private attributes and private methods of the class will be in the form of __class_name_attributes (methods) in the dir. Therefore, when the attributes and methods of the subclasses are in the form of the same name as those of the parent class, it does not overwrite the overrides. methods with the same name, it does not override the rewrite.

III Accessing and Modifying Private Properties and Private Methods of Classes

Classes can be encapsulated and protected by privatizing properties and methods. But what about when external access and changes are required? Just like TV sets, computers provide fixed interfaces to the outside world.
Above, while we can pass the class name(). _ class-name__ attribute (instance attribute) or class-name. _ ClassName__ attribute (class attribute), it is against the programming specification to do so, just as it would not be possible to unwrap a TV to manipulate it.

There are two general hair-splitting methods for correctly accessing the private properties and private methods of a class to modify them, as follows:

1. Customizing public methods

class D():
    __name = 'Zhang San'

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

    def __method(self):
        print("My name is{},last year{}year (of crop harvests),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()
    # Access private properties via get_value method
    print(d.get_value())
    # Access to private methods via the get_method method
    print('=' * 30)
    d.get_method()
    # Modify private attributes via the set_value method
    print('='*30)
    print(d.get_value())
    d.set_value('Wang Ermazi', 25, 'Linux')
    print(d.get_value())
    d.get_method()

Output results:

>>>
('Zhang San', 23, 'python')
==============================
My name is Zhang San, I'm 23 years old and I love python.
==============================
('Zhang San', 23, 'python')
('Wang Ermazi', 25, 'Linux')
My name is Wang Ermazi, I'm 25 years old, and I love Linux.

As you can see, we can access and modify private attributes and methods through our customized get_value(), get_method() and set_value() methods.

2. property

The property generally serves two purposes, as follows:

  • As a decorator, @property converts class methods to read-only class properties
  • property Reimplement the getter and setter methods for a property.

Take a look at this E class as follows:

class E():
    __name = 'Zhang San'

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

    def __method(self):
        print("My name is{},last year{}year (of crop harvests),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()
    # access
    print()
    e.get_method
    #Modify
     = 'Wang Er'
    print()

Results:

>>>
John Doe
My name is Zhang San, I'm 23 years old and I love python.
Wang Er (1962-), second son of Wang *

As you can see, we willget_valuecap (a poem)set_valueOnce the method is passed property, the class method is converted to a class property and assigned to the getValue variable. At this point it is read-only, i.e., the get_value method, and = 'Wang Er' is modified, i.e., theget_valuemethod. The same, via @propert, turns the get_method method, into a property.

the followingproperty Reimplement the getter and setter methods for a property, unlike the above, which is more common.

class E():
    __name = 'Zhang San'

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

    def __method(self):
        print("My name is{},last year{}year (of crop harvests),I like it.{}。".format(self.__name, self.__age, self.__luange))

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

if __name__ == '__main__':
    e = E()
    # access
    print()
    #Modify
    print("Before modification:", )
     = 'The Old King Next Door'
    print("Modified:", )

Output results:

>>>
John Doe
Before modification: the last table
Modified: The King Next Door

The above is to first send the name method to the property decorator for decoration, and then call the decorated setter method to realize the modification of the private property.

This article on Python object-oriented encapsulation details of the article is introduced to this, more related Python encapsulation content, please search for my previous articles or continue to browse the following related articles I hope you will support me in the future more!