0.继承
知识点:
继承: 子类默认能够使用父类的属性和方法
object: 所有类的父类,基类,超类,上帝类,祖宗类...
python3.x版本: 默认所有的类都继承了object类
子类: 也叫派生类
1.单继承
知识点:
单继承格式: class 子类名(父类名): pass
注意: 一个类可以有多个子类
示例:
# 单继承格式: class 子类名(父类名): pass
# 注意: 所有的类都默认继承了object类
# 先定义一个人类
class Person(object):
def study(self):
print('学习使我快乐')
# 学生类不想自己定义内容了,想用父类的属性和方法(前提父类需要存在)
class Student(Person):
pass
# 创建学生对象
s = Student()
# 学生对象调用人类方法(因为继承了人类,所以默认能够使用人类的属性和方法)
s.study()
2.单继承一个类可以有多个子类
知识点:
单继承格式: class 子类名(父类名): pass
注意: 一个类可以有多个子类
示例:
# 单继承格式: class 子类名(父类名): pass
# 注意: 所有的类都默认继承了object类
# 先定义一个人类
class Person(object):
def study(self):
print('学习使我快乐')
# 学生类不想自己定义内容了,想用人类的属性和方法(前提人类需要存在)
class Student(Person):
pass
# 教师类也可以去继承人类
class Teacher(Person):
pass
# 创建学生对象
s = Student()
# 学生对象调用人类方法(因为继承了人类,所以默认能够使用人类的属性和方法)
s.study()
# 创建教师对象
t = Teacher()
# 教师对象调用人类方法(因为继承了人类,所以默认能够使用人类的属性和方法)
t.study()
3.单继承练习
需求:
需求: 已知一个师父类,有传统配方属性,有传统制作煎饼果子方法,有一个徒弟想去学习,可以使用继承来完成
示例:
# 1.定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子')
# 2.定义徒弟类
class Prentice(Master):
pass
# 3.创建徒弟对象
p = Prentice()
# 4.徒弟对象获取从师父类继承下来的配方
print(p.secret)
# 5.徒弟对象使用从师父类继承下来的制作方法
p.make()
4.多继承
知识点:
多继承格式: class 子类名(父类名1,父类名2,父类名3...)
注意: 一个类可以有多个父类,但是默认使用第一个父类的同名属性和方法
示例:
# 需求: 有一个徒弟想去学习一开始目的是填饱肚子,继承了师父类,有传统配方属性,有传统制作煎饼果子方法,
# 填饱肚子后,想走上人生巅峰,选择继续去互联网创业,可以使用多继承来完成
# 1.1定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统煎饼果子配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子填饱肚子')
# 1.2定义CSDN学校类
class School(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '创业'
def make(self):
print(f'使用{self.secret}走上人生巅峰')
def study(self):
print('我现在在互联网深造')
# 2.定义徒弟类
# 注意: 如果继承多个父类,默认使用第一个父类的同名属性和方法
class Prentice(Master,School):
pass
# 3.创建徒弟对象
p = Prentice()
# 4.徒弟对象获取从父类继承下来的配方
print(p.secret)
# 5.徒弟对象使用从父类继承下来的制作方法
p.make()
# 6.徒弟对象直接调用继承下来的其他方法
p.study()
5.子类重写父类属性和方法
知识点:
子类重写父类属性和方法的目的?: 为了在原有基础上拓展功能(父类继承下来的不能满足子类需求)
注意: 如果重写了属性和方法,子类默认调用的是子类自己的同名属性和方法
示例:
# 需求: 有一个徒弟想去学习一开始目的是填饱肚子,继承了师父类,有传统配方属性,有传统制作煎饼果子方法,
# 填饱肚子后,想走上人生巅峰,选择继续去CSDN学Python,可以使用多继承来完成
# 徒弟类CSDN学习毕业后,独创编程语言开创了上市煎饼果子全国连锁公司,实现财富自由...
# 1.1定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统煎饼果子配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子填饱肚子')
# 1.2定义CSDN学校类
class School(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = 'CSDN'
def make(self):
print(f'使用{self.secret}走上人生巅峰')
def study(self):
print('我现在在学习Python')
# 2.定义徒弟类
# 注意1: 如果继承多个父类,默认使用第一个父类的同名属性和方法
# 注意2: 如果子类重写了父类的属性和方法,默认使用子类自己的同名属性和方法
class Prentice(Master, School):
def __init__(self):
self.secret = '独创编程语言'
def make(self):
print(f'使用{self.secret}开创了煎饼果子全国连锁上市公司,实现财富自由')
# 3.创建徒弟对象
p = Prentice()
# 4.徒弟对象调用同名属性
print(p.secret)
# 5.徒弟对象使用同名方法
p.make()
# 6.徒弟对象直接调用继承下来的其他方法
p.study()
6.子类调用父类的同名属性和方法
知识点:
子类调用父类同名属性和方法格式: 父类名.父类方法名(self)
示例:
# 需求: 有一个徒弟想去学习一开始目的是填饱肚子,继承了师父类,有传统配方属性,有传统制作煎饼果子方法,
# 填饱肚子后,想走上人生巅峰,选择继续去CSDN学python,可以使用多继承来完成
# 徒弟类CSDN学习毕业后,独创编程语言开创了上市煎饼果子全国连锁公司,实现财富自由...
# 实现了财务自由的时候,又回忆原来学习煎饼果子的经历或者CSDN的学习的经历
# 1.1定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统煎饼果子配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子填饱肚子')
# 1.2定义CSDN学校类
class School(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = 'CSDN'
def make(self):
print(f'使用{self.secret}走上人生巅峰')
def study(self):
print('我现在在CSDN学习深造')
# 2.定义徒弟类
# 注意1: 如果继承多个父类,默认使用第一个父类的同名属性和方法
# 注意2: 如果子类重写了父类的属性和方法,默认使用子类自己的同名属性和方法
# 注意3: 如果子类重写后又想调用父类同名方法: 父类名.父类方法名(self)
class Prentice(Master, School):
def __init__(self):
self.secret = '独创编程语言'
def make(self):
print(f'使用{self.secret}开创了煎饼果子全国连锁上市公司,实现财富自由')
# 想调用CSDN的同名属性和方法
School.__init__(self)
School.make(self)
# 想调用师父的同名属性和方法
Master.__init__(self)
Master.make(self)
# 3.创建徒弟对象
p = Prentice()
# 4.徒弟对象调用同名属性
print(p.secret)
# 5.徒弟对象使用同名方法
p.make()
# 6.徒弟对象直接调用继承下来的其他方法
p.study()
7.多层继承
知识点:
多层继承: 父子孙等多代关系
举例: 类A继承类B,类B继承类C ABC的关系就是多层继承
方法解析顺序: mro(method resolve order)
两种方式: 属性:__mro__ 方法:mro()
示例:
# 需求: 有一个徒弟想去学习一开始目的是填饱肚子,继承了师父类,有传统配方属性,有传统制作煎饼果子方法,
# 填饱肚子后,想走上人生巅峰,选择继续去CSDN学习Python,可以使用多继承来完成
# 徒弟类CSDN学习毕业后,独创编程语言开创了上市煎饼果子全国连锁公司,实现财富自由...
# 实现了财务自由的时候,又回忆原来学习煎饼果子的经历或者CSDN学习的经历
# 之前这些奋斗的东西,他的儿子直接继承(富二代)
# 1.1定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统煎饼果子配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子填饱肚子')
# 1.2定义CSDN学校类
class School(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = 'CSDN'
def make(self):
print(f'使用{self.secret}走上人生巅峰')
def study(self):
print('我现在在CSDN学习深造')
# 2.定义徒弟类
# 注意1: 如果继承多个父类,默认使用第一个父类的同名属性和方法
# 注意2: 如果子类重写了父类的属性和方法,默认使用子类自己的同名属性和方法
# 注意3: 如果子类重写后又想调用父类同名方法: 父类名.父类方法名(self)
class Prentice(Master, School):
def __init__(self):
self.secret = '独创编程语言'
def make(self):
print(f'使用{self.secret}开创了煎饼果子全国连锁上市公司,实现财富自由')
# 想调用CSDN的同名属性和方法
School.__init__(self)
School.make(self)
# 想调用师父的同名属性和方法
Master.__init__(self)
Master.make(self)
# 2.1 徒弟有了自己的儿子,儿子直接继承使用
# 多层继承: Son->Prentice->Master->School->object
class Son(Prentice):
pass
# 3.创建徒弟的儿子对象
s = Son()
# 4.徒弟的儿子对象调用同名属性
print(s.secret)
# 5.徒弟的儿子对象使用同名方法
s.make()
# 6.徒弟对象的儿子直接调用继承下来的其他方法
s.study()
# 7.获取方法解析顺序
# 方法mro() [<class '__main__.Son'>, <class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>]
print(Son.mro())
# 属性__mro__ (<class '__main__.Son'>, <class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
print(Son.__mro__)
8.super调用父类同名属性和方法
知识点:
super: 父类的代理
注意: super是根据mro顺序去查找 ,优先调用第一个父类同名方法
子类调用父类同名属性和方法3种方式:
方式1,通过父类名去调用: 父类名.父类方法名(self)
方式2,python3.x版本之前: super(当前类名,self).父类方法名()
方式3,python3.x版本: super().父类方法名()
示例:
# 需求: 有一个徒弟想去学习一开始目的是填饱肚子,继承了师父类,有传统配方属性,有传统制作煎饼果子方法,
# 填饱肚子后,想走上人生巅峰,选择继续去CSDN学大数据,可以使用多继承来完成
# 徒弟类CSDN学习完毕后,独创编程语言开创了上市煎饼果子全国连锁公司,实现财富自由...
# 实现了财务自由的时候,又回忆原来学习煎饼果子的经历或者CSDN学习的经历
# 之前这些奋斗的东西,他的儿子直接继承(富二代)
# 1.1定义师父类
class Master(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = '传统煎饼果子配方'
def make(self):
print(f'使用{self.secret}制作煎饼果子填饱肚子')
# 1.2定义CSDN学校类
class School(object):
def __init__(self):
# 由于是独一份配方,不需要传参,直接赋值
self.secret = 'CSDN'
def make(self):
print(f'使用{self.secret}走上人生巅峰')
def study(self):
print('我现在在CSDN学习深造')
# 2.定义徒弟类
# 注意1: 如果继承多个父类,默认使用第一个父类的同名属性和方法
# 注意2: 如果子类重写了父类的属性和方法,默认使用子类自己的同名属性和方法
# 注意3: 如果子类重写后又想调用父类同名方法: 父类名.父类方法名(self)
class Prentice(Master,School):
def __init__(self):
self.secret = '独创编程语言'
def make(self):
print(f'使用{self.secret}开创了煎饼果子全国连锁上市公司,实现财富自由')
# 想调用CSDN的同名属性和方法
School.__init__(self)
School.make(self)
# 想调用师父的同名属性和方法
Master.__init__(self)
Master.make(self)
# 使用super调用父类同名方法:
# 注意:按照mro方法解析顺序找,默认找的是第一个父类的同名属性和方法
super().__init__()
super().make()
# python3.x版本: 优化了python3.x版本之前的方式
# python3.x版本之前: super(当前类名,self).父类方法名()
super(Prentice,self).__init__()
super(Prentice,self).make()
# 2.1 徒弟有了自己的儿子,儿子直接继承使用
# 多层继承: Son->Prentice->Master->School->object
class Son(Prentice):
pass
# 3.创建徒弟的儿子对象
s = Son()
# 4.徒弟的儿子对象调用同名属性
print(s.secret)
# 5.徒弟的儿子对象使用同名方法
s.make()
# 6.徒弟对象的儿子直接调用继承下来的其他方法
s.study()
# 7.获取方法解析顺序
# 方法mro() [<class '__main__.Son'>, <class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>]
print(Son.mro())
# 属性__mro__ (<class '__main__.Son'>, <class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
print(Son.__mro__)
9.私有权限
知识点:
私有属性: _ _属性名
私有方法: _ _方法名()
私有属性和私有方法的效果: 隐藏到类中
1: 不能被外界直接访问
2: 不能被子类继承
示例:
# 私有权限能够达到隐藏效果: 类外不能直接访问属性和方法,本类中可以访问的
# 私有权限: 私有属性:__属性名 私有方法:__方法名()
# 1.定义类(类中定义私有属性和私有方法)
class Master(object):
def __init__(self):
self.name = '大师'
self.__money = 1000 # 私有属性
# 私有方法
def __house(self):
print('师父的私人别墅...')
# 徒弟类
class Prentice(Master):
def show(self):
print(self.name) # name是从Master类中继承下来的
print(self.__money) # 此行运行报错,因为私有属性和私有方法都不能被子类继承
# 2.创建大师对象
m = Master()
print(m.name) # 非私有属性能直接访问
# print(m.__money) # 测试是否能够直接访问私有属性? 不能 此行报错
# m.__house() # 测试是否能够直接方式私有方法? 不能 此行报错
# 3.创建徒弟对象
p = Prentice()
p.show()
10.修改和获取私有属性和调用私有方法
知识点:
私有属性: _ _属性名
私有方法: _ _方法名()
私有属性和私有方法的效果: 隐藏到类中,本类中是可以访问的
1: 不能被外界直接访问
2: 不能被子类继承
通过类中的公共方法间接访问私有属性: 设置,放: set_属性名 获取,拿: get_属性名
通过类中的公共方法间接调用私有方法: 展示: show_私有方法名
示例:
# 私有权限能够达到隐藏效果: 类外不能直接访问属性和方法,本类中可以访问的
# 封装: 把属性和方法隐藏起来,对外提供公共的方法,让外界通过公共方法访问
# 私有权限: 私有属性:__属性名 私有方法:__方法名()
# 1.定义类(类中定义私有属性和私有方法)
class Master(object):
def __init__(self):
self.name = '大师'
self.__money = 1000 # 私有属性
# 公共方法1:set_属性名()用于修改私有属性 set: 放 设置
def set_money(self, money):
self.__money += money # 存钱
# 公共方法2:get_属性名()用于获取私有属性 get: 拿 获取
def get_money(self):
return self.__money
# 私有方法
def __house(self):
print('师父的私人别墅...')
# 共有方法3: show_house用于调用私有方法 show: 展示
def show_house(self):
self.__house()
# 2.创建师父对象
m = Master()
print(m.name) # 非私有属性能直接访问
# print(m.__money) # 测试是否能够直接访问私有属性? 不能 此行报错,因为私有属性不能被外界直接访问
# m.__house() # 测试是否能够直接方式私有方法? 不能 此行报错,因为私有方法不能被外界直接访问
# 3.通过公共的接口间接访问私有属性
# 部队: 军事重地,闲人免进 通过门卫间接找到你朋友
# 通过get方法间接获取私有属性(查询)
print('保险箱原来的金额:', m.get_money())
# 通过set方法间接修改私有属性(存钱)
m.set_money(2000)
# 通过get方法间接获取私有属性(查询)
print('存了2000后的金额:', m.get_money())
# 4.通过公共的接口间接访问私有方法
m.show_house()
11.面向对象三大特性
知识点:
封装: 把属性和方法隐藏到类中,对外提供公共的接口(方法)
继承: 子类默认能使用父类的公共属性和方法,子类如果想拓展功能,可以去重写父类属性和方法
多态(了解): python中多态是伪多态: 同一个方法,传入不同的对象,实现不同的结果
示例:
# 定义基类:狗类
class Dog(object):
def work(self):
print('狗看家')
# 定义派生类: 军犬
class ArmyDog(Dog):
# 重写目的? 拓展功能
def work(self):
print('狗看家')
print('追击敌人...')
# 定义派生类: 缉毒犬
class DrugDog(Dog):
# 重写目的? 拓展功能
def work(self):
print('狗看家')
print('追查毒品...')
# 多态的前提: 继承 注意python中是伪多态
# 体验python中伪多态: 同一方法,传入不同对象,达到不同结果
class Person(object):
def dog_work(self, dog): # 引用地址传递: dog=ad dog=dd
dog.work() # ad.work() 或者 dd.work()
# 测试
zs = Person()
# dog_work方法中传递军犬对象
ad = ArmyDog()
zs.dog_work(ad)
# dog_work方法中传递缉毒犬对象
dd = DrugDog()
zs.dog_work(dd)
12.实例属性和类属性
知识点:
类属性
访问方式1: 类名.类属性名
方法方式2: 对象名.类属性名
1.内存存储不同:
实例属性: 每次都会给每个对象单独开辟一块空间,如果有一个属性是所有对象都一样的,实例属性就会浪费内存
类属性: 类属性是所有对象都会共享, 只会开辟一块空间, 相对节省内存,如果有一个属性是所有对象都一样的,建议使用类属性
2.位置不同:
实例属性: 方法内: self.实例属性 = 值
类属性: 类中方法外: 类属性 = 值
3.调用方式不同:
实例属性: 只能通过 对象名.实例属性 或者 self.实例属性 获取
类属性: 除了可以通过对象名或者self获取, 还可以通过 类名.类属性 获取
实例属性示例:
# 定义一个狗类
class Dog(object):
def __init__(self,name):
# 实例属性: 每个对象都会单独创建一次
self.name = name
self.tooth = 10 # 二哈和金毛都各自有一个实例属性tooth数量都是10,浪费内存
# 实例方法
def show(self):
print(self.name)
# print(Dog.tooth) #此行报错,实例属性只能通过实例对象访问
# 创建实例对象
eh = Dog('二哈')
# 通过对象名.实例属性获取年龄
print(eh.name,eh.tooth)
# 痛过对象名.实例方法名获取
eh.show()
jm = Dog('金毛')
print(jm.name,jm.tooth)
jm.show()
类属性示例:
# 定义一个狗类
class Dog(object):
# 类属性: 位置: 类中方法外 特点: 所有对象共有
tooth = 10 # 二哈和金毛共用一个类属性tooth,节省内存
def __init__(self, name):
# 实例属性位置: 方法内
# 实例属性: 每个对象都会单独创建一次
self.name = name
# 实例方法
def show(self):
print(self.name)
# 类属性可以 类名.类属性 直接访问,也可以实例对象访问 对象名.类属性
# 类属性只能通过类对象修改,不能通过实例对象修改
print(Dog.tooth)
# 实例对象1
eh = Dog('二哈')
print(eh.name, eh.tooth)
eh.show()
# 实例对象2
jm = Dog('金毛')
print(jm.name, jm.tooth)
jm.show()
print('---------------------------------')
# 修改类属性:只能通过类对象修改
Dog.tooth = 12
print(Dog.tooth) # 12
print(eh.name, eh.tooth) # 12
print(jm.name, jm.tooth) # 12
print('---------------------------------')
# 注意: 如果实例对象试图去修改类属性,不会报错,会给该对象单独创建一个和类属性同名的实例属性
eh.tooth = 22
print(Dog.tooth) # 12
print(eh.name, eh.tooth) # 22
print(jm.name, jm.tooth) # 12
13.类方法
知识点:
类方法装饰器: @classmethod
类对象: cls
注意: 类方法一般都是为了配合类属性使用
访问方式1: 类名.类方法名()
方法方式2: 对象名.类方法名()
示例:
# 定义类
class Dog(object):
# 定义类属性,私有化类属性
__tooth = 10
# 实例方法: self: 代表实例对象
def show1(self):
print(self.__tooth)
# 类方法 : cls: 代表类对象
@classmethod # 装饰器
def show2(cls):
print(cls.__tooth)
# 访问私有类属性
# 方式1: 类名.类属性
# print(Dog.tooth) # 报错,因为私有类属性不能被外界直接访问
# 方式2: 对象名.类属性
eh = Dog()
# print(eh.tooth) # 报错,因为私有类属性不能被外界直接访问
# 通过实例方法间接访问私有类属性
Dog.show1(eh) # 类名调用实例方法,必须手动传入实例对象
eh.show1() # python解释器自动传入
# 通过类方法间接访问私有类属性
# 方式1: 类名.类方法名()
Dog.show2()
# 方式2: 对象名.类方法名()
eh.show2()
14.静态方法
知识点:
为什么学静态方法?: 不用传递self,不用传递cls,相对节省内存
静态方法装饰器: @staticmethod
访问方式1: 类名.静态方法名()
方法方式2: 对象名.静态方法名()
示例:
# 定义类
class Dog(object):
# 定义静态方法 :使用装饰器 @staticmethod
# 为什么学静态方法? 实例方法必须传self
def show1(self):
print('这是一个实例方法')
# 为什么学静态方法? 类方法必须传cls
@classmethod
def show2(cls):
print('这是一个类方法')
# 为什么学静态方法? 不用传递self,不用传递cls
@staticmethod
def show3():
print('这是一个静态方法')
# 创建对象
d = Dog()
# 1.调用实例方法 :对象名.方法名()
d.show1()
# Dog.show1() #此行报错,实例方法不能直接通过类名访问
Dog.show1(d) # 实例方法通过类名调用时,必须手动传入实例对象
# 2.调用类方法 : 对象名.方法名() 类名.方法名()
d.show2()
Dog.show2()
# 3.调用静态方法 : 对象名.方法名() 类名.方法名()
d.show3()
Dog.show3()