一、组合
1.什么是组合
组合指的是一个对象中,包含另一个或多个对象。
2、组合作用
减少代码的冗余
ps:耦合度:
耦合度越高,程序的可扩展性越低;相反,耦合度越低,程序的可扩展性就越高
这里有个程序通过和继承的比较,可以显示这个作用。
1 # 继承 2 # 父类 3 class People: 4 def __init__(self, name, age, sex, year, month, day): 5 self.name = name 6 self.age = age 7 self.sex = sex 8 self.year = year 9 self.month = month 10 self.day = day 11 12 def print_birth(self): 13 print(f""" 14 ===== 出生年月日 ===== 15 年: {self.year} 16 月: {self.month} 17 日: {self.day} 18 """) 19 20 21 class Teacher(People): 22 pass 23 24 class Student(People): 25 pass 26 27 t1 = Teacher('张三', 24, '男', 1995, 1, 1) 28 s1 = Student('李四', 28, '女', 1991, 4, 1) 29 30 print(t1.year, t1.month, t1.day) 31 t1.print_birth() 32 print(s1.year, s1.month, s1.day) 33 s1.print_birth()
1 # 组合实现 2 class People: 3 def __init__(self, name, age, sex): 4 self.name = name 5 self.age = age 6 self.sex = sex 7 8 class Teacher(People): 9 pass 10 11 class Student(People): 12 pass 13 14 class Date: 15 def __init__(self, year, month, day): 16 self.year = year 17 self.month = month 18 self.day = day 19 20 def print_birth(self): 21 print(f""" 22 ===== 出生年月日 ===== 23 年: {self.year} 24 月: {self.month} 25 日: {self.day} 26 """) 27 28 t1 = Teacher('张三', 24, '男') 29 t_date = Date(1995, 1, 1) 30 t1.t_date = t_date 31 32 s1 = Student('李四', 28, '女') 33 s1_date = Date(1991, 4, 1) 34 s1.s1_date = s1_date 35 36 print(t1.t_date.year, t1.t_date.month, t1.t_date.day) 37 t1.t_date.print_birth()
组合练习:
练习需求:
选课系统:
1.有学生、老师类,学生与老师有属性 “名字、年龄、性别、课程”,
2.有方法 老师与学生可以添加课程, 打印学习/教授课程。
1 class People: 2 def __init__(self, name, age, sex): 3 self.name = name 4 self.age = age 5 self.sex = sex 6 7 # 打印出生日期方法 8 def print_birth(self): 9 print(f""" 10 年: {self.birthday.year} 11 月: {self.birthday.month} 12 日: {self.birthday.day} 13 """) 14 15 # 添加课程 16 def add_course(self, course_obj): 17 self.course_list.append(course_obj) 18 19 # 打印课程信息 20 def print_all_course(self): 21 # 从当前对象中课程列表中取出所有的课程对象 22 for course_obj in self.course_list: 23 course_obj.print_course() 24 25 class Teacher(People): 26 def __init__(self, name, age, sex): 27 super().__init__(name, age, sex) 28 self.course_list = [] 29 30 class Student(People): 31 def __init__(self, name, age, sex): 32 super().__init__(name, age, sex) 33 self.course_list = [] 34 35 class Date: 36 def __init__(self, year, month, day): 37 self.year = year 38 self.month = month 39 self.day = day 40 41 # def print_birth(self): 42 # print(f""" 43 # ===== 出生年月日 ===== 44 # 年: {self.year} 45 # 月: {self.month} 46 # 日: {self.day} 47 # """) 48 49 class Course: 50 def __init__(self, name, price, period): 51 self.name = name 52 self.price = price 53 self.period = period 54 55 # 定义打印课程方法,只打印一个课程信息 56 def print_course(self): 57 print(f""" 58 -------- 课程信息 -------- 59 课程名称: {self.name} 60 课程价格: {self.price} 61 课程周期: {self.period} 62 """) 63 64 65 # 创建学生对象 66 stu1 = Student("张三", 23, "男") 67 date_obj = Date('1996', '2', '14') 68 stu1.birthday = date_obj 69 stu1.print_birth() 70 71 72 # 创建课程对象 73 python = Course('python', 12312, 6) 74 linux = Course('linux', 13421, 4) 75 76 # 当前学生添加了课程对象 77 # 添加python课程 78 stu1.add_course(python) 79 # 添加linux课程 80 stu1.add_course(linux) 81 82 stu1.print_all_course()
小结:
- 继承:
继承是类与类的关系,子类继承父类的属性/方法,子类与父类是一种 “什么是什么” 关系。
- 组合:
组合是对象与对象的关系,一个对象拥有另一个对象中的属性/方法,是一种“什么有什么”的关系。
二、封装
1.什么是封装
封装指的是可以将一堆属性和方法,封装到对象中
PS: 对象就好比一个 “袋子/容器”,可以存放一对属性和方法。
PS: 存不是目的,目的是为了取,可以通过 “对象.” 的方式获取属性或方法。
2.封装作用
可以通过 “对象.” 的方式 “存放/获取” 属性或方法。
对象拥有 "." 的机制。
方便数据的存取。
三、限制访问机制
1.什么是限制访问机制
凡是在类内部定义的属性或方法,以__开头的属性或方法名,都会被限制,外部不能 “直接访问” 该属性原型,看着像将该属性或方法隐藏起来了
2.限制访问的作用
将一些隐私的数据,隐藏起来,不让外部轻易获取
- 接口:
可以将一对数据封装成一个接口, 可以让用户调用接口,
并且通过相应的逻辑,最后再将数据返回给用户。
凡是在类内部定义__开头的属性或方法,都会变形为 _类名__属性/方法
1 # demo1 2 class User: 3 # __开头的属性 4 __name = '张三' # __name变形为 ---》 _类名__name ---》 _User__name 5 # __开头的方法 6 def __func(self): 7 print('func') 8 9 print(User.__dict__) 10 user_obj = User() 11 print(user_obj._User__name) 12 user_obj._User__func()
1 # demo2 2 class User: 3 # __开头的属性 4 __name = '李四' # __name变形为 ---》 _类名__name 5 __age = 32 6 __sex = '男' 7 __ID = '412533198712245745' 8 __bal = 1500 9 # def __init__(self, name, age, sex): 10 # self.__name = name 11 # self.__age = age 12 # self.__sex = sex 13 # 校验接口,获取用户信息 14 def parse_user(self, username, password): 15 if username == 'tank_jam' and password == '123': 16 print(f''' 17 通过验证,获取用户信息。 18 用户名: {self.__name} 19 用户年龄: {self.__age} 20 用户性别: {self.__sex} 21 身份ID: {self.__ID} 22 用户资产: {self.__bal} 23 ''') 24 else: 25 print('校验失败, 无法查询用户信息!') 26 27 # __开头的方法 28 def __run(self): 29 print('tank is running...') 30 31 obj = User() 32 obj.parse_user('tank_jam', '123')
1 # demo3: 2 class ATM: 3 # 取钱功能: 4 # 1.插入磁卡 5 def __insert_card(self): 6 print('开始插卡...') 7 pass 8 9 # 2.输入密码 10 def __input_pwd(self): 11 print('输入密码...') 12 pass 13 14 # 3.输入取款金额 15 def __input_bal(self): 16 print('输入取款金额...') 17 pass 18 19 # 4.吐钱 20 def __output_money(self): 21 print('开始吐钱...') 22 pass 23 24 # 5.打印流水账单 25 def __print_flow(self): 26 print('打印流水账单...') 27 pass 28 29 # 取款顺序规范接口: 30 def withdraw(self): 31 # 1.插入磁卡 32 self.__insert_card() 33 34 # 2.输入密码 35 self.__input_pwd() 36 37 # 3.输入取款金额 38 self.__input_bal() 39 40 # 4.吐钱 41 self.__output_money() 42 43 # 5.打印流水账单 44 self.__print_flow() 45 46 47 amt_obj = ATM() 48 amt_obj.withdraw()
四、property
1.什么是property
是一个python内置的装饰器,可以装饰在"类内部的方法"上。
可以将该方法调用方式由 ----> 对象.方法() ---> 对象.方法
2.property作用
去掉()后,让名词的方法,调用时更为合理。
1 # 需求: 计算人体 bmi 指数 2 # 体重 / 身高的平方 3 # value = weight / (height * height) 4 class Bmi: 5 def __init__(self, name, weight, height): 6 self._name = name 7 self.weight = weight 8 self.height = height 9 @property 10 def bmi(self): 11 return self.weight / (self.height ** 2) 12 13 @property 14 def name(self): 15 return self._name 16 # 了解: 设置被property装饰后的方法 17 # 注意: 需要修改的方法名字要与被property装饰器后的方法一样 18 @name.setter 19 def name(self, value): 20 self._name = value 21 @name.deleter 22 def name(self): 23 del self._name 24 25 bmi_obj = Bmi('张三', 60, 1.8) 26 # print(bmi_obj.bmi()) 27 print(bmi_obj.bmi) 28 29 print(bmi_obj.name) 30 bmi_obj.name = '李四' 31 print(bmi_obj.name) 32 33 print(bmi_obj.__dict__) 34 del bmi_obj.name 35 print(bmi_obj.__dict__)