一、组合
1.什么是组合
组合指的是一个对象中的属性,是另一个对象
2.为什么使用组合
组合目的和继承一样,为了减少代码冗余
3.如果使用组合
class People: def __init__(self,name,age,sex,year,month,day): self.name=name self.age=age self.sex=sex self.year=year self.month=month self.day=day def tell_birth(self): print(f''' ===出生年月日=== 年:{self.year} 月:{self.month} 日:{self.day} ''') class Teacher(People): def __init__(self,name,age,sex,year,month,day): super().__init__(name,age,sex,year,month,day) class Student(People): def __init__(self,name,age,sex,year,month,day): super().__init__(name,age,sex,year,month,day) stu1=Student('壮壮',59,'female',1960,11,11) stu1.tell_birth() tea1=Student('坦克',30,'female',1990,1,1) tea1.tell_birth() 运行结果: ===出生年月日=== 年:1960 月:11 日:11 ===出生年月日=== 年:1990 月:1 日:1
#组合实现 class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex class Teacher(People): def __init__(self,name,age,sex): super().__init__(name,age,sex) class Student(People): def __init__(self,name,age,sex): super().__init__(name,age,sex) #日期类 class Date: def __init__(self,year,month,day): self.year=year self.month=month self.day=day def tell_birth(self): print(f''' ===出生年月日=== 年:{self.year} 月:{self.month} 日:{self.day} ''') tea1=Student('坦克',30,'female') date_obj=Date(2001,1,1) date_obj.tell_birth() #将Date对象赋值到tea1对象的date属性中 tea1.date=date_obj tea1.date.tell_birth() 运行结果: ===出生年月日=== 年:2001 月:1 日:1 ===出生年月日=== 年:2001 月:1 日:1
总结:继承--类与类的关系,一种什么是什么的关系,子类与父类是从属关系。
组合--对象与对象的关系,一种什么有什么的关系,一个对象拥有另一个对象。
4.组合练习
''' 选课系统需求: 1.学生类,老师类,学生和老师都有课程属性,每一门课程都是一个对象 课程:课程名字,课程周期,课程价钱。 2.学生和老师都有选择课程的功能,还有打印所有课程的功能 ''' class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex #添加一门课程的方法 def add_course(self,course_obj): self.course_list.append(course_obj) #打印当前对象中所有课程的课程信息 def tell_all_course(self): #拿到当前对象的课程列表,列表中存放的是一个个课程对象 for course_obj in self.course_list: #每一个课程对象调用查看课程信息的方法 course_obj.tell_course_info() class Teacher(People): def __init__(self,name,age,sex): super().__init__(name,age,sex) #用来存放课程对象 self.course_list=[] class Student(People): def __init__(self,name,age,sex): super().__init__(name,age,sex) #用来存放课程对象 self.course_list=[] #课程类 class Course: def __init__(self,course_name,course_period,course_price): #课程名称\周期\价格 self.course_name=course_name self.course_period=course_period self.course_price=course_price def tell_course_info(self): print(f''' 课程名称:{self.course_name} 课程周期:{self.course_period} 课程价钱:{self.course_price} ''') tea1=Teacher('tank',17,'male') stu1=Student('张全蛋',20,'female') python_obj=Course('python',6,2.0) linux_obj=Course('linux',6,1.0) #添加Python与Linux课程 tea1.add_course(python_obj) tea1.add_course(linux_obj) tea1.tell_all_course() 运行结果: 课程名称:python 课程周期:6 课程价钱:2.0 课程名称:linux 课程周期:6 课程价钱:1.0
二、封装
1.什么是封装?
封装指的是把一堆属性(特征与技能)封装到一个对象中。存数据的目的是为了取,对象可以用“.”的方式获取属性。
2.为什么要封装?封装的目的是为了方便存取,可以通过对象.属性的方式获取属性。
3.如何封装
特征:变量--数据属性
技能:函数--方法属性
在类内部,定义一堆属性(特征与技能)。通过对象.属性=属性值
访问限制机制
1.什么是访问限制机制?
在类内部定义,凡是以__
开头的数据属性与方法属性,都会被Python内部隐藏起来,让外部不能直接访问类内部的__
开头的属性。
2.访问限制机制的目的?
一堆隐私的属性与不能被外部轻易访问的属性,可以隐藏起来,不被外部直接调用。
好处:对重要数据获取的逻辑更加严谨,进而保证了数据的安全。
接口:隐私属性可以通过封装一个接口,在接口内做业务逻辑的处理,再把数据返回给调用者。
注意:Python中,不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形。若想直接访问,调用变形后的名字即可。
class Foo: #数据属性 __name='tank' #方法属性 def __run(self): print('running') #接口:获取数据接口 def get_name(self): return self.__name def set_name(self): self.__name='jsone' foo=Foo() # print(foo.__name) res=foo.get_name() print(res) #tank print(foo._Foo__name) #tank foo.set_name() print(foo.get_name()) #jsone
#demo2: class Teacher: def __init__(self,name,age,sex): self.__name=name self.__age=age self.__sex=sex #接口:打印用户信息接口 def get_info(self): #用户认证 user=input('user:').strip() pwd=input('pwd:').strip() if user=='tank' and pwd=='123': print(f''' 姓名:{self.__name} 年龄:{self.__age} 性别:{self.__sex} ''') #接口:修改用户信息接口 def set_info(self,name,age,sex): str1='string' #str('string') if not isinstance(name,str): raise TypeError('名字必须要使用字符串') if not isinstance(age,int): raise TypeError('年龄必须是数字') if not isinstance(sex,str): raise TypeError('性别必须使用字符串') self.__name=name self.__age=age self.__sex=sex tea1=Teacher('tank',17,'male') tea1.get_info() tea1.set_info('jseon',100,'female') tea1.get_info() 运行结果: user:tank pwd:123 姓名:tank 年龄:17 性别:male user:tank pwd:123 姓名:jseon 年龄:100 性别:female
#demo3:ATM class ATM: #1.插卡 def __insert_card(self): print('插卡') pass #2.输入密码 def __input_pwd(self): print('密码验证') pass #3.输入取款金额 def __input_money(self): print('输入金额') pass #4.开始吐钱 def __get__money(self): print('执行吐钱') pass #5.打印账单 def __print_flow(self): print('打印账单') pass #取钱直接接口 def withdraw(self): self.__insert_card() self.__input_pwd() self.__input_money() self.__get__money() self.__print_flow() print('取款程序执行完毕!') atm=ATM() atm.withdraw() 运行结果: 插卡 密码验证 输入金额 执行吐钱 打印账单 取款程序执行完毕!
三、property
1.什么是property
python内置的装饰器, 主要是给类内部的方法使用.
2.为什么要用property
使用它的目的,是将类内部的方法 (def 方法名()) 变成了 (def 方法). 在对象调用某个方法时,将对象.方法()变成对象.方法(看起来想一个普通的数据属性)
3.如何使用property
@property
''' 计算人体的bmi: bmi值 = 体重 / (身高 * 身高) ''' class People: def __init__(self, name, weight, height): self.name = name self.weight = weight self.height = height @property def bmi(self): return self.weight / (self.height * self.height) # 了解 @property def get_name(self): return self.name # 改 @get_name.setter def set_name(self, val): self.name = val # 删除 @get_name.deleter def del_name(self): del self.name p = People('jason', 200, 1.6) print(p.bmi) #-->不能对被装饰过的属性修改 #注意:不能对被装饰过的方法属性修改。 #了解:若真要通过此方法修改,可以通过另一种方式修改 print(p.get_name) p.set_name='tank' print(p.get_name) del p.del_name print(p.get_name)
四、多态
1.什么是多态?
多态指的是同一种事物的多种形态.
2.多态的目的:
多态也称之为多态性, 在程序中继承就是多态的表现形式.
多态的目的是为了, 让多种不同类型的对象, 在使用相同功能的情况下,调用同一个名字的方法名.
父类: 定义一套统一的标准.
子类: 遵循父类统一的标准.
多态的最终目的: 统一子类编写的规范, 为了让使用者更方便调用相同功能的方法.
3.如何实现:
继承
注意: 在python中,不会强制要求子类必须遵循父类的一套标准,所以出现了抽象类.
# 猪 class Pig: # 吃 def eat(self): print('猪在吃饭') pass # 喝 def drink(self): pass def speak(self): print('哼哼哼~~~') # 猫 class Cat: # 吃 def eat(self): print('猫在吃饭') pass # 喝 def drink(self): pass def speak(self): print('喵喵喵~~') # 狗 class Dog: # 吃 def eat(self): print('狗在吃饭') pass # 喝 def drink(self): pass def speak(self): print('汪汪汪~~~') dog = Dog() cat = Cat() pig = Pig() def BARK(animal): animal.speak() BARK(dog) BARK(cat) BARK(pig) str1 = '1234' list1 = [1, 2, 3] print(str1.__len__()) print(list1.__len__()) def LEN(d): return d.__len__() print(LEN(str1)) print(LEN(list1)) print(len(str1)) print(len(list1)) 运行结果: 汪汪汪~~~ 喵喵喵~~ 哼哼哼~~~ 4 3 4 3 4 3
五、抽象类
1.是什么?
abc模块 abstract_class
2.使用的目的?
强制子类必须遵循父类的一套标准.
3.如何使用
import abc
import abc class Animal(metaclass=abc.ABCMeta): # 吃 @abc.abstractmethod def eat(self): pass # 喝 @abc.abstractmethod def drink(self): pass # 叫 @abc.abstractmethod def speak(self): pass # 猪 class Pig(Animal): # 吃 def eat(self): print('猪在吃饭') pass # 喝 def drink(self): pass def speak(self): print('哼哼哼~~~') # 派生 def run(self): pass pig = Pig()
六、鸭子类型
1.什么是鸭子类型?
在不知道当前对象是何物的情况下,但是你长得像鸭子,那么你就是鸭子类型.
在python中,不推荐使用抽象类强制限制子类的定义,但是推荐类都遵循鸭子类型.
- 继承: 耦合性太高,程序的可扩展性差
- 鸭子类型: 耦合度低,程序的可扩展性强