encapsulation
Generally speaking, encapsulation is actually an object-oriented idea, which can protect code; narrowly speaking, encapsulation is one of the three characteristics of object-oriented, which can hide attributes and methods from people's eyes.
Private Attributes
Private attributes are represented by adding two double underscores before an attribute name
class Fighter: def __init__(self,name,hp,atk,speed): self.name = name self.__hp = hp #Private Attributes Deformation into self._Fighter__hp self.__atk = atk #Private Attributes Deformation to self._Fighter__atk self.__speed = speed #Private Attributes Deformation to self._Fighter__speed f1 = Fighter('AKK-18',1500,200,300) print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300}
python's private attributes only add a layer of privacy to the code level, and you are not allowed to access these private attributes directly, like if you print a private attribute whose result is an error, or if you want to try to modify a private attribute, the result can't be changed successfully.
f1.__hp = 1000 print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300, '__hp': 1000}
Because the above private attributes have been transformed into the format of class name attribute name, we write this as adding a new'key name'hp directly to self, so calling double underscores outside the class is not feasible.
How do we access our private attributes? We can see that the above private attributes have been transformed into the form of class name attribute name, so we can access:
print(f1._Fighter__hp) #1500 print(f1._Fighter__atk) #200 print(f1._Fighter__speed) #300
But such a shortcut is not perfect. We can add a get_value function inside the class to get those private attributes.
class Fighter: def __init__(self,name,hp,atk,speed): self.name = name self.__hp = hp #Private Attributes self.__atk = atk #Private Attributes self.__speed = speed #Private Attributes def get_value(self): return self.__hp,self.__atk,self.__speed #As long as private attributes are used within the class, they are automatically brought along'_Class name' f1 = Fighter('AKK-18',1500,200,300) print(f1.__dict__) #{'name': 'AKK-18', '_Fighter__hp': 1500, '_Fighter__atk': 200, '_Fighter__speed': 300} print(f1.get_value()) #(1500, 200, 300) for i in f1.get_value(): print(i) #1500 #200 #300
In get_value, return is actually a way of getting private attributes after deformations.
def get_value(self): return self._Fighter__hp,self._Fighter__atk,self._Fighter__speed
Private static properties
class Fighter: __id = 1234445 #Private static properties def __init__(self,name,hp,atk,speed): self.name = name self.__hp = hp #Private Attributes self.__atk = atk #Private Attributes self.__speed = speed #Private Attributes def get_value(self): #Getting Internal Private Attributes Method return self.__hp,self.__atk,self.__speed def get_id(self): return self.__id f1 = Fighter('AKK-18',1500,200,300) print(f1._Fighter__id) #1234445 print(f1.get_id()) #1234445
Private methods
class Fighter: __id = 1234445 #Private static properties def __init__(self,name,hp,atk,speed): self.name = name self.__hp = hp #Private Attributes self.__atk = atk #Private Attributes self.__speed = speed #Private Attributes def get_value(self): #Getting Internal Private Attributes Method return self.__hp,self.__atk,self.__speed def get_id(self): #Getting static attributes id Method return self.__id def __shoot(self): #Private methods print('Shooting!') def get_shoot(self): #Access to private methods shoot self.__shoot() #self._Fighter__shoot() f1 = Fighter('AKK-18',1500,200,300) f1.get_shoot() #Shooting!
Modifying private attributes
class Room: def __init__(self,name,length,width): self.__name = name self.__length = length self.__width = width def Area(self): return self.__width*self.__length def get_name(self): #How to get this private name return self.__name def set_name(self,new_name):#Reset the room number if type(new_name) is str and new_name.isdigit() == True: self.__name = new_name else: print('Incorrect naming!') r1 = Room('1101',15,20) print(r1.Area()) #300 print(r1.get_name()) #1101 r1.set_name('asd') print(r1.__dict__) #{'_Room__name': '1103', '_Room__length': 15, '_Room__width': 20} print(r1.get_name()) #1103
Several ornaments
1.@property
We often regard the circumference and area of a circle as a method when we write it in object-oriented way. However, we know that the method is an action of acquisition, not an attribute noun, so in order to deal with this kind of disguising a method as an attribute, we need to use @property, which makes it look like a method. It's an attribute.
from math import pi as P class Circle: def __init__(self,r): self.r = r def Perimeter(self): return 2*P*self.r def Area(self): return P*self.r**2 c = Circle(5) print(c.Area()) #78.53981633974483 print(c.Perimeter()) #31.41592653589793
Improvement:
from math import pi as P class Circle: def __init__(self,r): self.r = r @property def Perimeter(self): #Here it is. self No parameters can be passed back. return 2*P*self.r @property def Area(self): #Here it is. self No parameters can be passed back. return P*self.r**2 c = Circle(5) print(c.Perimeter) #31.41592653589793 print(c.Area) #78.53981633974483
BMI problem: BMI index (BMI) = body weight (kg), height ^ 2(m)
Adult BMI values:
Too light: below 18.5
Normal: 18.5-23.9
Overweight: 24-27
Very obese: > 32
class BMI: def __init__(self,height,weight): self.__height = height self.__weight = weight @property def __bmi(self): #Computation bmi Method masquerades as an attribute return self.__weight/self.__height**2 def get_bmi(self): #BMI judge if self.__bmi > 32: print('Very obese!') elif 24 <= self.__bmi <= 27: print('overweight!') elif 18.5 <= self.__bmi <= 23.9: print('normal!') else: print('Over light!') b = BMI(1.75,72) b.get_bmi() #normal!
Modify attributes with @setter on the premise of @property
class Person: def __init__(self,name,): self.__name = name @property def name(self): return self.__name + ' hello!' @name.setter def name(self,new_name): self.__name = new_name p1 = Person('Jogn') print(p1.name) #Jogn hello! #p1._Person__name = 'Maria' #Maria hello! print(p1.name) #Maria hello!
Delete attributes with @deleter on the premise of @property
class Person: def __init__(self,name,): self.__name = name @property def name(self): return self.__name + ' hello!' @name.deleter def name(self): del self.name p1 = Person('Jogn') print(p1.name) #Jogn hello! del p1.name #del p1.name Its role here is to point to deleter Here's how,Do the function of this method again print(p1.name) #I can't find the name.
Let's take a look at the del keyword here and what it does.
class Person: def __init__(self,name,): self.__name = name @property def name(self): return self.__name + ' hello!' @name.deleter def name(self): print('This method is implemented.!') p1 = Person('Jogn') print(p1.name) #Jogn hello! del p1.name #del p1.name Its role here is to point to deleter Here's how,Do the function of this method again print(p1.name) #Jogn hello!
Because there is no operation to modify the name in the second name, the original name can be printed in the last p1.name.
2.@classmethod
When this method involves only static attributes, it should be decorated with classmethod
class Goods: __discount = 0.8 #Discount? def __init__(self,name,price): self.name = name self.__price = price @property def price(self): return self.__price * self.__discount @classmethod def change_discount(cls,new_discount): #cls For class names cls.__discount = new_discount #Modify discount apple = Goods('Apple',4) print(apple.price) #3.2 Goods.change_discount(0.5) print(apple.price) #2.0
3.@staticmethod
In a fully object-oriented program, if a function has nothing to do with an object, then use static method to turn the function into a static method.
class Login: def __init__(self,name,password): self.name = name self.password = password @staticmethod def get_n_psw(): #Without default parameters, it's like a function. username = input('enter one user name:') psw = input('Please input a password:') Login(username,psw) #enter one user name:asdd return username,psw #Please input a password:4564648 print(Login.get_n_psw()) #('asdd', '4564648')