python encapsulation and binding

Keywords: Python

python encapsulation and binding

Object oriented has three characteristics: encapsulation, inheritance and polymorphism. This article mainly introduces class encapsulation and class binding.

  • Encapsulation: it means to integrate code, integrate data and functions, standardize code, better organize the overall structure of the project, reduce code redundancy and improve scalability

  • Class encapsulation is mainly divided into data encapsulation and method encapsulation

1. Encapsulation of data and methods

Examples are as follows:

# Before unpacking
name = 'HammerZe'
age = 18
gender = 'male'
print(f' name:{name}\n',
    f'age{age}\n',
      f'gender:{gender}')
# result
name:HammerZe
 age:18
 gender:male

In this way, it seems that the data are completely exposed, and the information of one person is so. Wouldn't it be troublesome if the information of multiple people is counted or modified in this way? Specify everyone's information format, which is more convenient to integrate first. It only needs a few lines of code to display all a person's information

# Data and method encapsulation
class Self_Info():
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender


# Encapsulation of methods / functions
    def view_info(self):
        print(f" name:{self.name}\n",
              f"age:{self.age}\n",
              f"gender:{self.gender}")

obj = Self_Info('HammerZe',18,'male')
obj.view_info()
# result
 name:HammerZe
 age:18
 gender:male

It seems that there are a lot more code after encapsulation. If you need to format and output other people's information next time, you just need to pass the parameters according to the format without redefining and rewriting, which standardizes the consistency of data and is easier to manage. In the previous article, we introduced the addition, deletion, query and modification of classes, so that personal information can be modified better without "pulling one hair and touching the whole body"

2. Hide properties

In Python, attributes within a class can be privatized, that is, hide data outside the class, and continue to operate data or methods within the class.

  • Private property format:__ Property name (data / method)

Examples are as follows:

'''Before private ownership'''
class Info():
    address = 'shanghai'

    def __init__(self, name, age, gender):
         self.name = name
         self.age = age
         self.gender = gender


    def get_info(self):
        print(f" name:{self.name}\n",
                       f"age:{self.age}\n",
                       f"gender:{self.gender}\n",
                       f"address:{self.address}")

obj = Info('HammerZe',18,'male')
obj.get_info()
# result
 name:HammerZe
 age:18
 gender:male
 address:shanghai
    
    
'''If we don't want to open personal addresses outside the class, we can privatize them'''
# Property private
__address = 'shanghai' # Just add _ to the data name, If you continue to obtain, an error will be reported
# Result > > > attributeerror: 'info' object has no attribute 'address'



# Property private
class Info():
    __address = 'shanghai' #Bottom layer:_ Info__address

    def __init__(self, name, age, gender):
         self.name = name
         self.age = age
         self.gender = gender


    def get_info(self):
        print(f" name:{self.name}\n",
                       f"age:{self.age}\n",
                       f"gender:{self.gender}\n",
                       f"address:{self.__address}") 
        
'''Get address prefix__'''
obj = Info('HammerZe',18,'male')
obj.get_info()
# result
 name:HammerZe
 age:18
 gender:male
 address:shanghai
    
'''Can't you get it if it's private? This only changes the data format. If you want to access it, you can access it by obtaining the data format'''
# Pass__ dict__ View namespaces and find__ The address format changes to_ Info__address
print(Info.__dict__)
# Therefore, the data format obtained outside the class can also be obtained
print(obj._Info__address) # shanghai
  • be careful! The data is the same as the private format of the method. Knowing the underlying format can also call / obtain the information in the method and data. The Internet is not absolutely safe

3. Open interface

  • The private principle of a class is external private, but it can be modified and continue to be used within the class. Defining attributes is for use

The calculator has many functions, but when we use it, we only need to input the number, and we can get the result through calculation. Then we don't need to know the underlying mathematical principle, just ask for the result, so many functions can be private and only expose the result to the user!

# Property private
'''Take power operation as an example'''
class Calculator():
    def __init__(self):
        self.num1 = int(input('Please enter base>>>:'))
        print(f'The base number you entered is{self.num1}')

    # exponentiation 
    def __pow(self,n):
       return self.num1**n

    def get_res(self):
        get_n = int(input('Enter the power to which you want to calculate the power operation>>>:'))
        res = self.__pow(get_n)
        print(f'The result of power operation is{res}')

num = Calculator()
num.get_res()

# result
 Please enter base>>>:22
 The base number you entered is 22
 Enter the power to which you want to calculate the power operation>>>:1
 The result of power operation is 22

'''In this way, we only need to input the number. The power operation function can be hidden and only exposed to the user function interface to return the result'''

4. Binding method

1. Object binding

class Info():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
'''The method bound to the object, called by the object, will pass itself to the function as the first parameter self'''

    def get_info(self):
        print(f'full name:{self.name}|Age:{self.age}')

obj = Info('HammerZe',18)
obj.get_info()
# result
# Name: HammerZe | age: 18

2. Class binding (classmethod)

class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    # @classmethod
    # def change(self):
    #     obj = self.__class__('HammerZe', 18)
    #     return obj
    '''Note that this method is equivalent to the following method'''
    @classmethod
    def change(cls):
        obj = cls('HammerZe', 18)
        return obj

# Generate object
stu = Student('ly',18)
print(stu.__dict__)
print(id(stu))

# Generate an object and receive it with a new object
obj = stu.change()
print(obj.__dict__)
print(id(obj))

'''stu.__class__.fun() equivalence Student.fun()'''
# Class call
obj1 = Student.change()
print(obj1.__dict__)
print(id(obj1))

3. Unbound method (staticmethod)

''' Count the number of objects generated by calling the class'''


class Count_obj():
    # Define count
    count = 0

    def __init__(self):
        Count_obj.count += 1

    # Static method / unbound method: neither bound to class nor object
    @staticmethod
    def count_info():
        print(f'Produced{Count_obj.count}Objects')


# Call class to generate object
obj = Count_obj()
obj1 = Count_obj()
obj2 = Count_obj()
obj3 = Count_obj()
obj4 = Count_obj()
# See how many objects were generated
Count_obj.count_info()

'''Note that the modification is in the class count,If self.count Can only be generated once in the namespace of an object count,Can not achieve the statistical effect'''

5. Property() function and property decorator

1. property() function

Format: property(fget=None, fset=None, fdel=None, doc=None)

  • fget: method to get property value
  • fset: method of setting attribute value
  • fdel: method for deleting attribute values
  • doc: attribute description information

Examples are as follows:

class Student:
    def __init__(self):
        self._age = None

    def get_age(self):
        print('Code to execute when viewing properties')
        return self._age

    def set_age(self, age):
        print('Code executed when setting properties')
        self._age = age

    def del_age(self):
        print('Code to execute when deleting a property')
        del self._age

    age = property(get_age, set_age, del_age, 'Student age')


student = Student()
# Note to use the class name. Attribute__ doc__  View the document string of the property as
print('To view the document string for a property:' + Student.age.__doc__)
"""
Document string for viewing properties: student age
"""

# set a property
student.age = 18
"""
Code executed when setting properties
"""

# View properties
print('Student age:' + str(student.age))
"""
Code executed when getting properties
 Student age: 18
"""

# Delete attribute
del student.age
"""
Code to execute when deleting a property
"""
print(student.__dict__) # {}

2. property decorator

The property decorator can "disguise" the function in the class as the data property of the object. When the object accesses the special property, it will trigger the execution of the function, and then take the return value as the result of this access

  • @The property syntax provides a more concise and intuitive way to write than the property() function.

  • The method decorated by @ property is the method to obtain the property value. The name of the decorated method will be used as the property name.

  • The method decorated with the @ property name. setter is the method of setting the property value.

  • The method decorated by @ attribute name. Delete is the method to delete the attribute value.

The following example code is equivalent to the code using the property() function version:

class Student:
    def __init__(self):
        self._age = None

    @property
    def age(self):
        print('Code to execute when viewing properties')
        return self._age

    @age.setter
    def age(self, age):
        print('Code executed when setting properties')
        self._age = age

    @age.deleter
    def age(self):
        print('Code to execute when deleting a property')
        del self._age


student = Student()

# set a property
student.age = 18
"""
Code executed when setting properties
"""

# get attribute
print('Student age:' + str(student.age))
"""
Code to execute when viewing properties
 Student age: 18
"""

# Delete attribute
del student.age
"""
Code to execute when deleting a property
"""

3. Attention!

  • You can omit the method of setting the property value, and the property becomes read-only. If the attribute is still set at this time, an exception AttributeError: can't set attribute will be thrown.
  • If the error recursionerror is reported: maximum recursion depth exceeded while calling a python object, it is likely that the object property name and the method name decorated with @ property are the same. Generally, an underscore will be added before the object property name_ Avoid duplicate names and indicate that this is a protected attribute.

property reference:

[to be continued]

Posted by glueater on Fri, 03 Dec 2021 03:35:44 -0800