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]