面向对象_new
2023-04-08 15:29:20 5 举报
AI智能生成
python_面向对象
作者其他创作
大纲/内容
三大特性
继承
场景
当两个类中有相同或相似的静态变量或绑定方法时,
使用继承可以减少代码的重用,提高代码可读性,规范编程模式
使用继承可以减少代码的重用,提高代码可读性,规范编程模式
语法
单继承
class 子类(父类):pass
class A: pass
class B(A):pass
class B(A):pass
object类
python3中所有类都继承objdec类
多继承
class 子类(父类1, 父类2...): pass
class A: pass
class B: pass
class C(A, B): pass
class B: pass
class C(A, B): pass
C类继承A类和B类,享有A类和B类中的成员
多继承中,子类对象通过类指针找成员时,根据继承顺序依次寻找,
例如:class C(A, B): pass, C 类对象在访问本类中没有的成员时,
优先在A类中找,A类中没有再去B类中找
例如:class C(A, B): pass, C 类对象在访问本类中没有的成员时,
优先在A类中找,A类中没有再去B类中找
方法重写
1.子类重写父类中的同名方法
子类对象在调用方式时,只会执行子类自己的方法;
如果既要执行子类中的同名方法,又要执行父类中的同名方法,
可在子类方法中主动调用父类同名方法:父类名.方法名(self)
可在子类方法中主动调用父类同名方法:父类名.方法名(self)
2.子类添加自己独有的属性(派生属性)
子类重写__init__方法,先调用父类的__init__方法来初始化共有属性,
再在子类自己的init方法中初始化子类独有的属性(派生属性)
再在子类自己的init方法中初始化子类独有的属性(派生属性)
# 父类
class Animal:
def __init__(self, name, blood):
self.name = name
self.blood = blood
class Animal:
def __init__(self, name, blood):
self.name = name
self.blood = blood
# 子类
class Cat(Animal):
def __init__(self, name, blood, eye_cloor):
# 调用父类init方法,初始化通用属性
Animal.__init__(self, name, blood)
self.eye_color = eye_color # 派生属性
class Cat(Animal):
def __init__(self, name, blood, eye_cloor):
# 调用父类init方法,初始化通用属性
Animal.__init__(self, name, blood)
self.eye_color = eye_color # 派生属性
父类和子类方法选择
单继承
1.子类对象,如果去调用方法,永远优先调自己的
2.如果子类自己有,用子类自己的
3.子类没有,用父类的
4.如果子类自己有,还想用父类的:
直接在子类中调用父类的方法:父类名.方法名(self)
直接在子类中调用父类的方法:父类名.方法名(self)
多继承
一个类有多个父类,在调用父类方法的时候,按照继承顺序,
先继承的就先寻找
先继承的就先寻找
isinstance(obj, classType)
语法:
判断一个对象是什么类型,返回True, False
用途
判断一个类是不是继承某一个父类
ret = isinstance(Student, People)
print(ret) # True
print(ret) # True
instance与type的区别
type函数只能判断一个对象是不是某个类型;
不能判断一个对象是否继承自某个父类
不能判断一个对象是否继承自某个父类
instance既可以判断对象是否属于某个类,
也可以判断对象是否继承自某个父类
也可以判断对象是否继承自某个父类
class People(object):
pass
class Student(People):
pass
if __name__ == '__main__':
stu1 = Student()
print(type(stu1) is Student) # True
print(type(stu1) is People) # False
print(isinstance(stu1, Student)) # True
print(isinstance(stu1, People)) # True
pass
class Student(People):
pass
if __name__ == '__main__':
stu1 = Student()
print(type(stu1) is Student) # True
print(type(stu1) is People) # False
print(isinstance(stu1, Student)) # True
print(isinstance(stu1, People)) # True
绑定方法和普通函数(了解)
from type import FunctionType, MethodType
FunctionType: 函数
类中的方法,通过类名调用,就是函数
MethodType: 方法
类中的方法通过对象调用,就是方法
from types import FunctionType,MethodType
# FunctionType : 函数
# MethodType : 方法
class A:
def func(self):
print('in func')
print(A.func) # 函数
a = A()
print(a.func) # 方法
print(isinstance(a.func,FunctionType)) # False
print(isinstance(a.func,MethodType)) # True
print(isinstance(A.func,FunctionType)) # True
print(isinstance(A.func,MethodType)) # False
# FunctionType : 函数
# MethodType : 方法
class A:
def func(self):
print('in func')
print(A.func) # 函数
a = A()
print(a.func) # 方法
print(isinstance(a.func,FunctionType)) # False
print(isinstance(a.func,MethodType)) # True
print(isinstance(A.func,FunctionType)) # True
print(isinstance(A.func,MethodType)) # False
经典类和新式类
在python3中都是新式类
在python2中默认是经典类
python2解释器,在类定义时主动继承object类,就会变成新式类
类的继承顺序
单继承:深度优先
无论是经典类还是新式类,单继承都是深度优先
多继承
经典类:深度优先
新式类:广度优先
简单多继承内存图
小乌龟模型
C3算法
# 算法的内容
# 如果是单继承 那么总是按照从子类->父类的顺序来计算查找顺序
# 如果是多继承 需要按照自己本类,父类1的继承顺序,父类2的继承顺序,..
# 如果是单继承 那么总是按照从子类->父类的顺序来计算查找顺序
# 如果是多继承 需要按照自己本类,父类1的继承顺序,父类2的继承顺序,..
merge规则
如果一个类出现在从左到右所有顺序的最左侧,并且没有在其他位置出现,那么先提出来作为继承顺序中的一个
或 一个类出现在从左到右顺序的最左侧,并没有在其他顺序中出现,那么先提出来作为继承顺序中的一个
如果从左到右第一个顺序中的第一个类出现在后面且不是第一个,那么不能提取,顺序向后继续找其他顺序中符合上述条件的类
或 一个类出现在从左到右顺序的最左侧,并没有在其他顺序中出现,那么先提出来作为继承顺序中的一个
如果从左到右第一个顺序中的第一个类出现在后面且不是第一个,那么不能提取,顺序向后继续找其他顺序中符合上述条件的类
理解即可,重点记住类名.mro方法,查看类的继承顺序
抽象类
(软件开发规范)
(软件开发规范)
定义:
规范子类必须实现父类的同名方法,方便在子类中提供统一接口;
记住:
所有类都必须继承object类,如果见到了抽象类,一定要在子类中
实现同名方法.
规范子类必须实现父类的同名方法,方便在子类中提供统一接口;
记住:
所有类都必须继承object类,如果见到了抽象类,一定要在子类中
实现同名方法.
方式一:
在父类成员方法中主动raise异常,在子类调用同名方法时抛异常
(raise NotImplementedError(message))
在父类成员方法中主动raise异常,在子类调用同名方法时抛异常
(raise NotImplementedError(message))
方式二:
通过导入abc模块下的ABCMeta类、abstractmethod函数实现;
缺点:依赖第三方模块;
优点:强约束,子类如果未重写父类中被abstractmethod装饰的方法,
子类在实例化的时候就会报错
通过导入abc模块下的ABCMeta类、abstractmethod函数实现;
缺点:依赖第三方模块;
优点:强约束,子类如果未重写父类中被abstractmethod装饰的方法,
子类在实例化的时候就会报错
队列和栈
定义:
队列(queue): 先进先出
栈(stack): 先进后出
通过继承方式实现队列和栈
super关键字
语法
1.访问父类属性
super().父类属性名
super(子类名, self).父类属性名
2.调用父类成员方法
super().方法名(形参)
super(子类名, self).父类方法名(形参列表)
注意:在py2的新式类中,super方法必须主动传当前子类的类名和self
super在单继承和多继承中的区别
1.在单继承中,super就是指父类
2.在多继承中,super是按照mro顺序来寻找当前类的下一类
还是不太懂,实践出真知
封装
1.定义
1.广义上的封装
把属性和方法封装到类中,类外不能直接调用了,要通过类的名字来调用
2.狭义上的封装
类中的成员(静态变量、实例变量、绑定方法)私有化,只能在本类内部使用
3.封装实际就是java中用private修饰的成员,如果想对外提供访问或修改的入口,
可根据需求对外提供私有成员的getter/setter方法;
可根据需求对外提供私有成员的getter/setter方法;
2.私有化类的成员
1.私有化静态变量
__静态变量名
2.私有化实例变量
def __init__(self, pwd):
self.__pwd = pwd
self.__pwd = pwd
3.私有化绑定方法
__绑定方法
3.类成员私有化后不能从类的外部调用的原因?
1.成员私有化之后,都默认在私有成员前面加了: _类名__私有成员,
这样类外在直接访问 ‘__私有成员’ 时,就会提示属性或方法不存在;
可通过:对象名.__dict__ / 类名.__dict__ 查看私有成员
这样类外在直接访问 ‘__私有成员’ 时,就会提示属性或方法不存在;
可通过:对象名.__dict__ / 类名.__dict__ 查看私有成员
2.成员私有化之后,在类内调用时,会自动在私有成员前面补充上 '_类名',
所以私有成员可以在类内访问
所以私有成员可以在类内访问
注意:类的成员私有化后,只能在本类中使用,类外和子类都不能使用
py支持的封装级别
1.public
公共的: 类内、类外、父类、子类
2.private
私有的:只有本类内部可以访问
多态
定义
1.一个类表现出来的多种状态,实际上是通过继承来完成的。
父类具有子类类型的多种形态(多个子类继承同一个父类)
父类具有子类类型的多种形态(多个子类继承同一个父类)
2.在python中处处是多态,因为python定义成员时没有强制定义类型
3.在Java如果想接受多个类型的对象,必须用父类来指定数据类型:
例如:所以如果想让两个类型的对象都可以传,
那么必须让这两个类继承自一个父类,在指定类型的时候使用父类来指定
例如:所以如果想让两个类型的对象都可以传,
那么必须让这两个类继承自一个父类,在指定类型的时候使用父类来指定
# java中的多态是什么样
# def eat(动物类型 猫的对象/狗的对象,str 食物):
# print('动物类型保证了猫和狗的对象都可以被传递进来')
# def eat(动物类型 猫的对象/狗的对象,str 食物):
# print('动物类型保证了猫和狗的对象都可以被传递进来')
场景
1.结合isinstance方法判断一个对象是不是属于某个父类,
如果是的话,就可以调用这个父类中的成员
如果是的话,就可以调用这个父类中的成员
2.通过多态对外提供归一化设计接口,在接口内部利用
多态实例化子类并调用子类方法
多态实例化子类并调用子类方法
继承中的归一化设计
设计思路:对外提供统一的接口供第三方使用,
当需求变更时,不改变第三方使用者的调用方式
当需求变更时,不改变第三方使用者的调用方式
# 归一化设计
# class A:
# def 同名功能(self):pass
# class B:
# def 同名功能(self):pass
#
# def 函数名(obj):
# obj.同名功能()
# class A:
# def 同名功能(self):pass
# class B:
# def 同名功能(self):pass
#
# def 函数名(obj):
# obj.同名功能()
支付场景:
1.父类约束子类实现同名pay方法
2.对外提供统一的支付接口;
根据支付方式,实例化不同的对象
根据支付方式,实例化不同的对象
类的3个装饰器用法
property
1.被装饰的方法,不能有参数
2.被装饰的方法可以通过类名/对象名.的方式调用,
伪装成类的属性
伪装成类的属性
3.被装饰方法可与私有属性搭配使用,
方便类外对私有属性的查询、修改、删除
方便类外对私有属性的查询、修改、删除
4.property装饰的成员方法,
添加查询修改删除装饰器,
以间接修改类中私有成员
添加查询修改删除装饰器,
以间接修改类中私有成员
@property
def 绑定方法(self):pass
def 绑定方法(self):pass
@方法名.setter
@方法名.getter
@方法名.deleter
classmethod
staticmethod
反射
定义
反射:就是用字符串数据类型的名字,来操作这个名字对应的函数、实例变量、绑定方法、等各种方法
sys.modules
查看已经加载到内存中的所有模块,字典形式
sys.modules['__main__'] : 当前文件(脚本)
反射三大器
1. hasattr(__obj: object, __name: str)
判断__name 在 __obj中是否存在, 返回True, False
2. getattr(__obj: object, name: str)
反射__obj中的与name名字相同的成员
3. callable(__obj: object)
判断 obj是否可调用, 返回True/False
当需要判断反射的对象是否可调用时,先把反射的对象作为参数传递给callable,
如果返回True,再给反射对象加括号调用
如果返回True,再给反射对象加括号调用
反射三大器demo
反射的应用场景
1.反射模块(导入的其他模块)中的内容
2.反射当前文件(脚本)中的内容
3.反射类中成员(静态成员或静态方法)
4.反射对象的属性或绑定方法
反射的例子(归一化设计接口)
1.抽象类_重写父类pay方法
2.利用反射对外提供统一支付接口
面向对象初识
类
定义:类是具有相同属性和行为的一类事物
类的命名空间:类在加载时会在呢库存中开辟一块内存空间,存储类中定义的所有成员
成员变量
成员方法
类中的成员
1.成员变量/静态变量
2.成员方法
默认带有self参数(指向 对象的内存地址)
__init__ 方法:类实例化时自动调用,
其他成员方法,通过对象调用
对象.成员方法() # 相当于: 类名.成员方法(对象)
类的静态成员
访问类中的成员
类名.静态成员
修改类的静态成员
类名.静态成员 = 修改后的值
给类增加新的静态成员
类名.变量名 = 初始值
使用场景
1.如果一个变量,是所有对象共享的值,那么这个变量应该定义成静态变量
2.所有和静态变量相关的增删改查,都使用类名来处理
类名.__dict__
返回一个字典,包含类的所有成员信息
成员变量
成员方法
对象
对象/实例
给类中的所有属性填上具体的值就是一个对象或者实例
实例化
taibai = Persion('taibai', 'male', 18)
实例 = 类名(属性..)
实例变量
self.属性名/方法名
实例化过程
1.类加载时,在内存中开辟一块属于类的空间
a.类的成员变量(静态变量)
类中的成语变量归该类的所有对象共有
b.成员方法
__init__(self, 形参1, 形参2...)
其他成员方法: 类中具有的行为
2.开辟一块属于self的空间
a.该空间通过类指针,指向类本身的空间
b.调用 __init__方法,把属于对象的内存地址传递给 __init__ 方法的形参self
c. __init__ 方法把实例化传递的实参存储在self空间里 -- 对象的初始化
d.init方法的形参self所指向的内存地址会作为返回值,返回给实例对象
taibai = Persion('taibai', 'male', 18)
实例(对象)属性
实例变量的增删改
通过对象名.属性的方式实现增删改查
注意点:
# 类中的变量是静态变量
# 对象中的变量只属于对象本身,每个对象有属于自己的空间来存储对象的变量
# 当使用对象名去调用某一个属性的时候会优先在自己的空间中寻找,找不到再去对应的类中寻找
# 如果自己没有就引用类的,如果类也没有就报错
# 对于类来说,类中的变量所有的对象都是可以读取的,并且读取的是同一份变量
# 对象中的变量只属于对象本身,每个对象有属于自己的空间来存储对象的变量
# 当使用对象名去调用某一个属性的时候会优先在自己的空间中寻找,找不到再去对应的类中寻找
# 如果自己没有就引用类的,如果类也没有就报错
# 对于类来说,类中的变量所有的对象都是可以读取的,并且读取的是同一份变量
对象.静态变量
对象.静态变量可以访问类的静态成员变量,
但不能进行赋值操作,否则就会在对象自己的空间中创建和静态变量同名的实例变量
但不能进行赋值操作,否则就会在对象自己的空间中创建和静态变量同名的实例变量
统计类被实例化次数
"""
实现一个类,能够自动统计这个类实例化了多少个对象
"""
class A():
"""
统计类实例化次数
"""
Count = 0
def __init__(self):
A.Count += 1 # 每个实例对象都共享同一个静态成员变量Count
for i in range(10):
A()
print(A.Count) # 10
实现一个类,能够自动统计这个类实例化了多少个对象
"""
class A():
"""
统计类实例化次数
"""
Count = 0
def __init__(self):
A.Count += 1 # 每个实例对象都共享同一个静态成员变量Count
for i in range(10):
A()
print(A.Count) # 10
对象名.__dict__
返回一个字典,包含对象的所有属性和值
对象的组合问题
场景:
一个类的对象时另一个类对象的属性
例如:班级和课程类,班级实例对象中包含课程类的属性
优点
通过修改某一个对象实例的属性,就可以批量修改所有使用该对象实例作为属性的实例对象
案例:
# 练习 :
# 对象变成了一个属性
# 班级类
# 包含一个属性 - 课程
# 课程
# 课程名称
# 周期
# 价格
# 创建两个班级 linux57
# 创建两个班级 python22
# 查看linux57期的班级所学课程的价格
# 查看python22期的班级所学课程的周期
# 对象变成了一个属性
# 班级类
# 包含一个属性 - 课程
# 课程
# 课程名称
# 周期
# 价格
# 创建两个班级 linux57
# 创建两个班级 python22
# 查看linux57期的班级所学课程的价格
# 查看python22期的班级所学课程的周期
class Student:
"""
学生类
"""
def __init__(self,name,sex,age,number,clas,phone):
self.name = name
self.sex = sex
self.age = age
self.number = number
self.clas = clas
self.phone = phone
"""
学生类
"""
def __init__(self,name,sex,age,number,clas,phone):
self.name = name
self.sex = sex
self.age = age
self.number = number
self.clas = clas
self.phone = phone
class Clas:
"""
班级类
"""
def __init__(self,cname,begint,teacher, course):
self.cname = cname
self.begint = begint
self.teacher = teacher
self.course = course
"""
班级类
"""
def __init__(self,cname,begint,teacher, course):
self.cname = cname
self.begint = begint
self.teacher = teacher
self.course = course
class Course():
"""
课程类
"""
def __init__(self, cname, period, price):
self.cname = cname
self.period = period
self.price = price
"""
课程类
"""
def __init__(self, cname, period, price):
self.cname = cname
self.period = period
self.price = price
linux = Course('linux', '5 Month', '19800.00')
python = Course('python', '6 Month', '20000.00')
linux57 = Clas('linux57', '20230101', 'wusir', linux)
python22 = Clas('python22', '20230228', 'taibai', python)
print(linux57.course.price)
print(python22.course.price)
linux57.course.price = '21500.00'
print(linux57.course.price)
python = Course('python', '6 Month', '20000.00')
linux57 = Clas('linux57', '20230101', 'wusir', linux)
python22 = Clas('python22', '20230228', 'taibai', python)
print(linux57.course.price)
print(python22.course.price)
linux57.course.price = '21500.00'
print(linux57.course.price)
对象和类内容回顾
# 类
# class 类名:
# 静态变量 = '值'
# def 函数(self):
# '函数体的内容'
# pass
# 所有的变量和函数的地址都存储在类的命名空间里
# 对象
# 对象 = 类名()
# 怎么用
# 类能做什么用?
# 1.实例化对象
# 2.操作静态变量
# 什么时候是对类中的变量赋值,或者去使用类中的变量
# 类名.名字 = '值'
# print(类名.名字)
# print(对象名.名字) # 如果对象本身没有这个名字
# 什么时候是对对象中的变量赋值
# 对象.名字的时候
# self.名字的时候
# class 类名:
# 静态变量 = '值'
# def 函数(self):
# '函数体的内容'
# pass
# 所有的变量和函数的地址都存储在类的命名空间里
# 对象
# 对象 = 类名()
# 怎么用
# 类能做什么用?
# 1.实例化对象
# 2.操作静态变量
# 什么时候是对类中的变量赋值,或者去使用类中的变量
# 类名.名字 = '值'
# print(类名.名字)
# print(对象名.名字) # 如果对象本身没有这个名字
# 什么时候是对对象中的变量赋值
# 对象.名字的时候
# self.名字的时候
类和对象的命名空间
命名空间总结:
1.假设你想要一个类的某个属性是各自对象自己的,那么把它定义在__init__方法中
2.假设你想要一个类的摸个属性让所有对象共享,那么把它定义成静态变量
1.对象名.的方式给实例对象添加属性
2.类中静态成员指向一块空间,
对象修改静态变量值,此时所有对象都会访问修改后的值
对象修改静态变量值,此时所有对象都会访问修改后的值
3.对象空间有的属性,只改对象自己的
4.类中存在重名成员时,后定义的成员会覆盖先定义的成员
案例1:本类中没有在父类中找
案例2:在子类中调用父类成员方法
案例3:同案例2
案例4:子类对象修改本类中的静态成员变量
案例5:子类对象修改父类中的静态成员变量
案例6:子类对象修改对象自己的属性
案例7:对象在找成员变量或成员方法时,
遇到self总是先回子类对象或子类中找,
找不到在去父类中找
遇到self总是先回子类对象或子类中找,
找不到在去父类中找
鸭子类型(魔术方法)
定义:
定义:不通过继承来实现一个类属于某个类,这个类就是鸭子类型
例如:只要实现了__iter__和__next__方法的类,就是迭代器类
例如:只要实现了__iter__和__next__方法的类,就是迭代器类
dir(对象/类型):以列表形式返回当前类中有哪些方法
# 鸭子类型
# 子类继承父类,我们说子类是父类类型的(猫类继承动物,我们说猫也是动物)
# 在python中,一个类是不是属于某一个类型
# 不仅仅可以通过继承来完成
# 还可以是不继承,但是如果这个类满足了某些类型的特征条件
# 我们就说它长得像这个类型,那么他就是这个类型的鸭子类型
# 子类继承父类,我们说子类是父类类型的(猫类继承动物,我们说猫也是动物)
# 在python中,一个类是不是属于某一个类型
# 不仅仅可以通过继承来完成
# 还可以是不继承,但是如果这个类满足了某些类型的特征条件
# 我们就说它长得像这个类型,那么他就是这个类型的鸭子类型
代码实例:
常见鸭子类型
__base__
查看子类继承的第一个父类,所有类默认继承object
__bases__
查看子类继承的所有父类
__dict__
对象.__dict__
查看多想的所有属性
类名.__dict__
查看类的所有成员
包含调用类的模块和成员变量、成员方法
__name__
函数名.__name__
返回函数名
类名.__name__
返回类名
__class__
返回所属类型,默认都是: <class 'type'>
__module__
返回当前类的所在的模块名
场景:打印日志时,通过 类名.__module__, 记录出问题的类在那个文件中,方便排查问题
__doc__
返回类或函数中的文档注释
类名.__doc__
函数名.__doc__
__len__
计算可迭代类型长度
__iter__
可迭代
__next__
取迭代器的元素
pickle\json实现多次写多次读
1.封装pickle模块:
实现多次写入,多次读取
实现多次写入,多次读取
pickle支持的序列化类型:
支持Python所有的数据类型包括实例化对象
支持Python所有的数据类型包括实例化对象
2.封装json模块:
实现多次写入,多次读取
实现多次写入,多次读取
Json支持的序列化类型:
json序列化只支持部分Python数据结构:
dict,list, tuple,str,int, float,True,False,None
json序列化只支持部分Python数据结构:
dict,list, tuple,str,int, float,True,False,None
抽象类+反射归一化设计封装json和pickle类
抽象类约束子类
反射实现归一化设计接口
选课系统需求
https://www.cnblogs.com/Eva-J/articles/9235899.html
0 条评论
下一页