Article Directory
1. What is packaging?
In a program, encapsulation is an abstraction of concrete objects.
Simply put: hide some parts (privatization), other parts of the program are invisible (there is no way to call directly)
Privatization: privatize features or some methods in the class, making it impossible to directly use externally
2. The benefits of packaging
- Protect privacy — hide the parts that you don’t want the outside world to know
- Isolate the complexity ----- hide the complex implementation in the program -> provide a simple interface [method] to use the private content
- Improve the robustness of the code
- Add necessary judgments according to actual needs
3. How to package
- Generally, the attribute is privatized, and the corresponding set and get methods are provided for the attribute
- Add two underscores before the property name to privatize
Why privatize?
- Can be called directly or modified at will
- After modification, it does not meet the needs of real life -> bug -> can not be modified at will
- Simply put, it is to add a condition before the modification, and then let you modify the condition when the condition is met.
class Student:
def __init__(self, name, age, sex):
self.name = name
# self.age = age
self.__age = age # 加两个下划线私有化
self.sex = sex
def main():
stu = Student("诡途", 18, '男')
print(stu.name)
# print(stu.age)
# print(stu.__age)
# 也可以在外部进行随意的修改
stu.age = -10 # 不满足实际生活需求-->bug-->不能让外界随意修改
print(stu.age)
if __name__ == '__main__':
main()
After privatization, it cannot be called through attributes, nor can it be modified! But it needs to be called and modified.
Therefore, it is necessary to provide a simple interface for obtaining
-
Provide an interface for assignment:
- The assignment is performed by the outside world, and the value is passed in when it needs to be called from the outside. The assignment interface needs to have a formal parameter
- Pseudo code of assignment method
def set_字段名(self, 代表字段名的形参): if 条件: self.__字段名 = ?? elif 条件: self.__字段名 = ?? else: self.__字段名 = 代表字段名的形参 #(或者是在if|elif下,根据实际需求写)
-
Provide the value interface:
- The outside world only wants to get the value of this field, and does not want to pass the value, the interface for the value needs to have a return value
- Pseudo code of the value method
#伪代码 def get_字段名(self): return self.__字段名
Private package complete code
class Student:
def __init__(self, name, age, sex):
self.name = name
# self.__age = age
# 因为初始化时,也是由外界赋值的,
# 所以在初始化时,也需要判定数据的合理性,再进行赋值
# 因为判断数据合理性已经封装成方法了,所以直接调用赋值方法即可
self.set_age(age)
self.sex = sex
def set_age(self, age):
# 可以按照实际生活需求加入逻辑判断
if age < 0:
# 设置默认值
self.__age = 0
else:
self.__age = age
def get_age(self):
return self.__age
def main():
stu = Student("诡途", 18, '男')
stu_age = stu.get_age()
print(stu_age)
# 调用设置的接口
stu.set_age(-10)
stu_age = stu.get_age()
print(stu_age)
# 对象的特征值是动态赋予的
if __name__ == '__main__':
main()
set and get do not necessarily appear in pairs, write as needed
4. Attributed get and set methods
- Attributed----> It can be called as if it has not been encapsulated when it is called outside
- Property call: object. Property name
- Method call: object. method name ()
- After the get and set methods are attributed — the format of calling them is similar to that of directly calling attributes
How to attribute it?
- The way to attribute the get method----> a decorator provided by the system @property
- Attributed the set method ----> A setter decorator created on the basis of the attributed get method -> Attributed the set method -> Format: @getmethod name.setter
[For details about decorators, see] The artifact that modifies the functions of other functions-python decorator
Code sample
class Person:
def __init__(self, name, age, sex):
# 这些特征称之为对象的属性
self.name = name
self.age = age
# self.set_sex(sex)
# 属性化后,要按照属性的方式进行赋值
# self.set_sex = sex
# 修改方法名
self.sex = sex
#
# @property
# def get_sex(self):
# return self.__sex
@property
def sex(self):
return self.__sex
# @get_sex.setter
# def set_sex(self, sex):
# if sex != "男" and sex != "女":
# self.__sex = "男"
# else:
# self.__sex = sex
@sex.setter
def sex(self, sex):
if sex != "男" and sex != "女":
self.__sex = "男"
else:
self.__sex = sex
# 在类的外部获取对象的属性
p = Person("诡途", 18, "男")
# 获取属性的方式: 对象.属性名
print(p.name)
# # 直接调用get方法
# value = p.get_sex()
# print(value)
# 属性化之后调用 --》只能通过属性化的方式来调用
# value = p.get_sex # 属性化之后 等价于 get_sex()() 等价于 "男"() ==》报错TypeError: 'str' object is not callable
# print(value)
# 属性化之后,把对属性的修改映射回,封装之前那样对属性进行修改或者获取
# 对于正常的属性进行赋值
p.name = "图图"
# 对私有化属性进行赋值
# p.set_sex("女")
# # 属性话后进行赋值
# p.set_sex = "女"
# print(p.get_sex)
p.sex = "女"
print(p.sex)
Because the general field name is not modified by set and get, generally when naming the get method and set method, they are directly named as the field name