面向对象 Object Oriented
学习面向对象:XXOO
面向对象的学习:
面向对象的语法(简单,记忆就可以搞定)
面向对象的思想(稍难,需要一定的理解)
面向过程和面向对象的区别:
面向过程开发,以函数作为基本结构使用:
吃饭 -> 吃饭的函数
喝水 -> 喝水函数
洗衣服 -> 洗衣服的函数
睡觉 -> 使用充气娃娃的函数
看电影 -> 买票开电影函数
....
面向对象的开发,以对象作为基本结构使用:
女朋友{
喂饭功能
喂水功能
洗衣服功能
陪你睡觉功能
陪你看电影功能
....
}
吃饭->调用女盆友的喂饭功能
喝水->调用女朋友的喂水功能
洗衣服->调用女朋友的洗衣服功能
睡觉->调用女朋友的陪睡功能
...
面向对象的开发非常适合大型程序开发,开发速度和后期维护都比过程化开发要好很多。同时 也会降低一点效率。
语言中对象结构的特色:高内聚,低耦合。
面向对象相关的单词:
OO 面向对象
OOP 面向对象的程序开发
OOA 面向对象的分析
OOD 面向对象的设计
OOI 面向对象的实现
OOA -> OOD -> OOI 面向对象的实现过程
类和对象
什么是类?
人类就是一个类
动物类也是一个类
鸟类就是一个类
女朋友也是一个类
基友也是一个类
瓶子都是一个类
类是一个实物的特征的集合,是抽象的概念。
打蛋蛋是一个类
XXOO 也是一个类
撩妹也是一个类
开车也是一个类
打人也是一个类
类也是行为和操作的概念的集合。也是不具体的操作,没有真正操作过。
类是抽象的概念,仅此而已!
什么是对象?
霍云瑞这个人他是一个对象
霍云瑞家的那个小鸡鸡是一个对象
霍云瑞的第一个女朋友就是一个对象
霍云瑞的当前的基友就是一个对象
这个瓶子就是一个对像。
教室后面那个空调就是一个对象。
对象就是具体存在的看得见摸得着的某个实物。
昨天霍云瑞打一次自己的蛋蛋,就是一个对象
今天中午霍云瑞吧马浚龙XXOO了就是一个对象
今天上午霍云瑞吧马俊龙撩了就是一个对象
马俊龙今天晚上把霍云瑞打了,这就是一个对象
真实发生过得行为就是对象
对象一定是具体的或者发生过的事物!
类和对象的关系
类是多个对象归纳总结而来的,是一种概念,包含所有对象。
由对象总结出类的过程,叫做抽象化
对象是类的具体实现或者实施而来,他是真实的,特指某个事物
由类制作出对象的过程,叫做实例化
如何书写类文件
推荐使用驼峰命名法来书写文件:
驼峰命名法:
类名:每个单词的首字母大写
人类 Person
开车 DriveCar
撩妹 LiaoMei
....
函数名/变量:除了第一个单词之外首字母大写
马俊龙 maJunLong
约炮函数 yuePao 或者yue_pao(不是驼峰命名)
一个文件如果是一个单独的类,那么直接使用类名来当作文件名即可
类的组成
类中只有2种内容:成员属性和成员方法
成员属性:
用于描述类的特征的变量就是成员属性
成员方法:
用于描述类的功能的函数就是成员方法
类的书写规则
- 必须使用class关键字来声明一个类
- 类的名称需要符合驼峰命名法(规范)
- 类中只能存在2种内容,成员属性和成员方法,除此之外,所有的代码都禁止出现!
- 声明成员属性时,所有成员属性必须有值,如果没值会报错!,推荐使用None等值代替
- 成员方法只需要按照函数的规则声明即可
实例化对象
对象变量 = 类()
类的类型为 type
类的值就是类本身
对象的类型为类
对象的值,对象本身 <main.Person object at 0x020DC650>
检测类和对象的成员
检测类成员
类名.__dict__
检测对象成员
对象.__dict__
类和对象成员的操作
1.类成员操作
访问类中成员
类名.成员属性名
类名.成员方法名() (没有参数要求,所有方法都可以通过类访问)
修改类中成员:
类名.成员属性名 = 值
类名.成员方法名 = 新值 (如果需要函数只能用lambda)
删除类中成员:
del 类名.成员属性名
del 类名.成员方法名()
添加类中成员:
类名.新成员属性名 = 值
类名.新成员方法名 = 值 (如果需要函数只能用lambda)
2.对象成员操作
访问对象中成员
对象变量.成员属性名
对象变量.成员方法名() (必须有一个用于接收对象本身的形参)
修改对象中成员:
对象变量.成员属性名 = 值
对象变量.成员方法名 = 新值 (如果需要函数只能用lambda)
删除对象中成员:
del 对象变量.成员属性名
del 对象变量名.成员方法名()
添加对象中成员:
对象变量.新成员属性名 = 值
对象变量.新成员方法名 = 值 (如果需要函数只能用lambda)
关于self (他不是关键字,是一个随意书写的字符串而已)
1.英文单词的意义 :自己
2.绑定类的方法,只能通过类来访问的方法,就是绑定类的方法
3.非绑定类的方法,就是可以通过对象访问的方法就是非绑定的方法
4.绑定类与非绑定类的方法不取决于语法,而取决于设计者如何设计该方法
5.一般情况下非绑定类的方法第一个参数写单词self,但是这不是唯一的单词,写什么都行,self不是关键字,不是关键字,不是关键字!
面向对象的三大特性
面向对象都具有三大特性:封装,继承和多态
封装特性
封装就是对类和对象的成员访问进行限制,设定可以访问的方式和不可以访问的方式。
封装的三个级别:
私有化封装 -> private 英文单词而已不是关键字
受保护的封装 -> protected 英文单词而已不是关键字
公共的封装 -> public 英文单词而不是关键字
检测封装的三个位置:
类中/对象中
类外部/对象外部
子类中
私有化封装 private
私有化封装是最高级别的封装。私有化封装之后的成员,只能在类中/对象中访问,类的外部,子类中都不可以访问到。
私有化封装: 在成员名称前添加2个_即可
例如:封装heart -> __heart
python将heart 改名为_类名__成员名
类中/对象中 可以访问
类外/对象外 不可以访问
子类/子类对象 不可以访问
注意:在python中实现的封装操作,不是通过权限限制而是通过改名(name mangling 改名策略)实现的。名字变了找不到而已。可以通过 对象._类名 _方法或类名.类名 __方法名访问到(禁止这么干)
受保护的封装 protected
受保护的封装是一定级别的封装,封装之后,只有部分位置可以访问(类和子类),部分位置(类外)不可以访问。
受保护的封装: 在成员名称前添加1个_即可
例如:受保护 money -> _money
类中/对象中 可以访问
类外/对象外 可以访问(原则上类外不行,但是没实现)
子类/子类对象 可以访问
注意:受保护的封装依旧是通过name mangling的方式修改了成员的名称而已, 可以通过对象.类名成员 或者类名.类名成员的方式访问(别这么干)
公共的封装 public
所有的成员默认都是公共的封装级别,可以在类中,类外,及子类中正常访问
类中/对象中 可以访问
类外/对象外 可以访问
子类/子类对象 可以访问
继承
继承就是可以获取另外一个类中的成员属性和成员方法。(并非所有成员)
作用:继承的作用是增加代码的复用性,节省不必要的重复代码,提高开发效率,同时可以设置类之间的关系。
继承的两个概念:
父类
用于被继承的类,称之为父类 ,也叫做基类,或者超类
子类
继承其他类的类,称之为子类, 也叫做派生类
继承的格式
class 父类:
pass
class 子类(父类):#继承操作的关键步骤
pass
继承的特征
- 所有类都是继承自object类(object类对应的对象就是object对象,也是万物皆对象)
- 子类继承父类则可以访问父类的所有成员。(私有成员除外)
- 子类继承父类并不会将父类的所有成员复制到子类当中去,子类访问成员是访问父类的成员,
- 子类可以具有自己独有的属性和方法
- 子类可以重载父类中的方法,只需要设置和父类指定成员相同的名称即可实现重载,重载之后的成员,子类只会访问当前类中的成员,而不会调用父类中同名的成员
- 子类中如果重载父类的方法,并且还想将重载的父类方法借调过来使用,可以在重载的方法中使用 【父类名.方法()】(适合类) 或者 【super().方法()】(适合对象)
单继承和多继承
单继承:每个类只能继承一个类的方式称为单继承。
多继承:每个类可以同时继承多个类的方式称为多继承。
python属于多继承语言!,但是一般不用
多继承格式:
class 父类1:
pass
class 父类2:
pass
class 子类(父类1,父类2):
pass
多继承之后,子类就具备了所有父类的成员(私有成员除外)
多个父类具有相同的成员时,子类继承[继承列表]中第一个类的方法
菱形继承/钻石继承
#菱形继承格式
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B,C):
pass
A
/ \
B C
\ /
D
菱形继承存在的问题
如果BC类同时继承了A类,D类又继承了BC两个类的情况下(菱形继承),
在调用BC中某个同名方法(该方法都继承自A类)时会导致继承自A类的该方法被多次调用。导致逻辑问题!
所以python使用 super()类来解决了多继承的菱形继承问题
MRO列表
Method Realtion Order 为了制作一个继承关系的列表而已。
python3中使用C3算法来计算了MRO列表(计算过程暂时忽略)
MRO列表的制作原则:
1.子类永远在父类的前面
2.如果继承了多个父类,那么按照()中的顺序在列表中摆放
3.如果多个类同时继承了一个父类,孙子类中只会选取第一个父类中的父类的该方法
super()
super不是一个关键字,也是不是有函数,他是一个类
super()的作用不是查找父类,而是找MRO列表的上一个类
super()和父类没有任何实质性的关系,只是有时候能调用到父类而已。
在单继承的情况下,super()永远调用的是父类/父对象
格式:
super().方法() python3的格式
没事别用多继承!!
mixin 设计模式
该设计模式的主要作用是采用多继承方式,进行类的扩展。
优点:
1.mixin可以在对类不做任何修改的情况下,扩展类的功能(添加父类)
2.可以方便的组织和维护各种不同组件的划分。
3.可以根据需要任意调整
4.可以避免创建更多的类,也可以避免继承导致的混乱
#水果类
class Fruit:
pass
#礼物类和非礼物类
class Gift:
pass
class NotGift:
pass
#南方北方类
class South:
pass
class North:
pass
#爽和不爽的苹果
class Cool:
pass
class NotCool:
pass
#真实水果类
class Apple(Fruit,Gift,North,NotCool):
pass
class Pear(Fruit,NotGift,North,NotCool):
pass
class Banana(Fruit,NotGift,North,Cool):
pass
class Orange(Fruit,Gift,South,NotCool)
类的常用函数
issubclass() 检测一个类是否是另外一个类的子类
格式1: issubclass(被检测类,父类)
返回值:布尔值
格式1: issubclass(被检测类,(父类1,父类2,父类3...))
返回值:布尔值
注意:只要有一个类是当前被检测类的父类,那么最终结果就是True
isinstance() 检测一个对象是否是某个类的对象
格式1: isinstance(对象,类)
返回值:布尔值
格式2: isinstance(对象,(类1,类2,类3...))
返回值:布尔值
注意:只要一个类是当前对象的类,那么最终结果就是True
hasattr() 检测对象/类是否具有某个成员
格式:hasattr(对象/类,'成员名')
返回值:布尔值
getattr() 获取对象/类中的成员值
格式:getattr(对象,'成员名'[,成员不存在时的默认值])
返回值:成员的值
setattr() 设置或者添加对象/类中的成员
格式:setattr(对象,'成员名',值)
返回值:None
delattr() 删除对象/类中的成员
格式: delattr(对象,成员)
返回值:None
dir() 获取对象的成员名称列表
格式:dir(对象)
返回值:列表
property() 用于设置成员属性的修饰符
格式:成员属性 = property(获取的方法,设置的方法,删除的方法)
描述符
python中的描述符是用于描述对象中的属性。主要作用就是对属性操作提供限制,验证,管理等相关权限的操作。
描述符主要有三种操作需要设置:
get 获取属性的操作
set 设置属性的操作
delete 删除属性的操作
描述符方法1
#描述符类
class Description:
#成员属性
#name = ''
#初始化方法
def __init__(self):
#为当前类/对象添加一个成员属性(当前类)来接收需要描述的成员属性(要描述的类)此处还没有接收(占位)
self.name = None
#get获取属性值的方法
def __get__(self,obj,cls):# self 用于接收当前描述符类的对象 obj 接收用于管理的成员的对象 cls 用于接收管理成员的类
print('获取方法被触发')
self.name = str(self.name)
return self.name[:4]
#set设置属性值的方法
def __set__(self,obj,val): #self 用于接收当前描述符类的对象 obj 接收用于管理的成员的对象 val 设置的值
print('设置方法被触发')
#print(self,obj,val)
#在此处可以添加限制和判断(密码奇数时*2)
if val %2 == 1:
val *= 2
#完成了(email)对象的属性值的设置
self.name = val
#delete 删除属性值的方法
def __delete__(self,obj): #self当前描述符类的对象 obj 接收用于管理的成员的对象
#用户代为删除操作
del self.name
#声明一个邮箱的类
class Email:
#属性
#用户名
account = '[email protected]'
#密码(为密码设置了描述符 的对象) 这一步相当于吧password的所有传入了Description的对象当中
password = Description()
#------实例化对象
email = Email()
#1设置密码
email.password = 7758520
#2获取密码
print(email.password)
#3删除密码
del email.password
#获取密码
print(email.password)
描述符方法2:
#邮箱类
class Email:
#成员属性
#为username添加描述符
#username = ''
#设置邮箱账号最大的长度
maxlength = 6
#为描述符添加一个临时变量(在描述符中代替username进行操作)
tmpusername = None
password = ''
#成员方法
#为username的描述符进行设置(添加方法)
#获取username的描述符方法
def getusername(self):
print('获取操作被触发')
#返回值之前进行值的修饰,两边添加星星
if self.tmpusername != None:
self.tmpusername = '★' + self.tmpusername + '★'
#设置获取username的时候的值
return self.tmpusername
#设置username的描述符方法
def setusername(self,val):
print('设置操作被触发')
#限制,根据Email类的最大账号长度对用户名进行截取之后在设置
#检测val是否是字符串类型
if isinstance(val,str):
val = val[0:self.maxlength]
self.tmpusername = val
#删除username的描述符方法
def delusername(self):
print('删除操作被触发')
#删除操作
del self.tmpusername
#为username设置描述符
username = property(getusername,setusername,delusername)
3.属性修饰符
#邮箱类
class Email:
#用户名
username = ''
#密码
password = ''
#使用描述符来操作昵称
#昵称
petname = '小乖乖'
#为描述符设置临时变量
_petname = None
#成员方法(暂无)
#描述符设置的三个部分 获取,设置和删除
#处理petname获取操作
@property
def petname(self):
print('获取操作被触发')
return self._petname
#处理petname的设置操作
@petname.setter
def petname(self,val):
print('设置操作被触发')
#设置操作
self._petname = val
#处理petname的删除操作
@petname.deleter
def petname(self):
print('删除操作被触发')
#删除操作
del self._petname
类的内置属性
__dict__ 获取当前类/对象成员组成的字典
__doc__ 获取当前类/对象的文档,和函数一样使用''' 定义即可
__name__ 类.__name__是获取当前类名,如果直接写__name__则是获取模块的名称
__bases__ 获取类的继承列表中所有父类组成的元组
魔术方法:
常用魔术方法
魔术方法就是一个类/对象中的方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法是在特定时刻自动触发。
1._ _ init _ _() 初始化魔术方法1 ★★★★★=
触发时机:初始化对象时触发(不是实例化触发,但是和实例化在一个操作中)
参数:至少有一个self,接收对象
返回值:无
作用:初始化对象的成员
注意:使用该方式初始化的成员都是直接写入对象当中,类中无法具有
2._ _ new _ _ 实例化魔术方法!
触发时机: 在实例化对时触发
参数:至少一个cls 接收当前类
返回值:必须返回一个对象实例
作用:实例化对象
注意:实例化对象是Object类底层实现,其他类继承了Object的_ _ new _ _才能够实现实例化对象。没事别碰这个魔术方法,先触发 _ _ new _ _ 才会触发 _ _ init _ _
3._ _ del _ _ 析构魔术方法
触发时机:当对象没有用(没有任何变量引用)的时候被触发
参数:一个self 结婚搜对象
返回值:无
作用:使用完对象是回收资源
注意:del不一定会触发当前方法,只有当前对象没有任何变量接收时才会触发
4._ _ call _ _ 调用对象的魔术方法
触发时机:将对象当作函数调用时触发 对象()
参数:至少一个self接收对象,其余根据调用时参数决定
返回值:根据情况而定
作用:可以将复杂的步骤进行合并操作,减少调用的步骤,方便使用
注意:无
5._ _ len _ _
触发时机:使用len(对象) 的时候触发
参数:一个参数self
返回值:必须是一个整型
作用:可以设置为检测对象成员个数,但是也可以进行其他任意操作
注意:返回值必须必须是整数,否则语法报错,另外该要求是格式要求。
6._ _ str _ _
触发时机:使用print(对象)或者str(对象)的时候触发
参数:一个self接收对象
返回值:必须是字符串类型
作用:print(对象时)进行操作,得到字符串,通常用于快捷操作
注意:无
7._ _ repr _ _
触发时机:在使用repr(对象)的时候触发
参数:一个self接收对象
返回值:必须是字符串
作用:将对象转使用repr化为字符串时使用,也可以用于快捷操作
repr函数和str函数处理字符串只有一个区别:
str的结果 字符串本身 (结果可以被eval执行)
例如:x = '霍云瑞' str() ->霍云瑞
rerpr的结果 字符串定义结构 (eavl不会执行repr结果)
例如:x = '霍云瑞' repr() ->'霍云瑞'
备注: 在类中通常情况下str和repr 设置相同即可
eval() 函数 将字符串当作python代码执行
格式:eval(字符串)
返回值:可以有返回值
8._ bool _
触发时机: 使用bool(对象)的时候触发
参数:一个self接收对象
返回值:必须是布尔值
作用:根据实际情况决定,可以作为快捷方式使用
注意:仅适合于返回布尔值的操作
9._ format _
触发时机:使用字符串.format(对象)时候触发
参数:一个self接收对象,一个参数接收format的{}中的格式,例如:>5
返回值:必须是字符串
作用:设置对象可以作为format的参数,并且自定义对象格式化的规则
注意:无
描述符相关的魔术方法
1.get()
触发时机:在获取指定描述符操作的成员属性的值的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象,描述符描述的对象的类
返回值:必须有,不然无法获取相应属性值
注意:仅在描述符中使用
2.set()
触发时机:在设置或者添加指定描述符操作的成员属性的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象,3要设置的值
返回值:无
注意:仅在描述符中使用
3.delete()
触发时机:在删除指定描述符操作的成员属性的时候触发
参数:1描述符对象本身,2描述符描述的属性所在的对象
返回值:无
注意:仅在描述符中使用
与属性操作相关的魔术方法
1._ _ getattr _ _()
触发时机:获取不存在的对象成员时触发
参数:1接收当前对象的self,一个是获取成员名称的字符串
返回值:必须有值
作用:为访问不存在的属性设置值
注意:getattribute无论何时都会在getattr之前触发,触发了getattribute就不会在触发getattr了
2._ _ setattr _ _()
触发时机:设置对象成员值的时候触发
参数:1个当前对象的self,一个是要设置的成员名称字符串,一个是要设置的值
返回值:无 过程操作
作用:接管设置操作,可以在设置前之前进行判断验证等行为
注意:在当前方法中无法使用成员=值的方式直接设置成员,否则会无限递归,必须借助object的设置方法来完成
object.__setattr__(参数1,参数2,参数3)
3._ deleteattr_()
触发时机:删除对象成员时触发
参数:一个当前对象的self
返回值:无
作用:可以在删除成员时进行验证。
4._ _ getattribute _ _()
触发时机:使用对象成员时触发,无论成员是否存在
参数:1个接收当前对象self,一个是获取的成员的名称字符串
返回值:必须有
作用:在具有封装操作(私有化时),为程序开部分访问权限使用
5.dir()
触发时机:dir(对象)的时候触发
参数:1个接收当前对象self
返回值:必须为序列类型(列表,元组,集合等,)
作用:可以自定义成员列表的返回值
运算相关魔术方法(上帝模式)
比较运算相关魔术方法
1._ _lt_ _()
格式:
def __lt__(self,other):
return 数据
特征:
触发时机:进行小于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义小于号的行为:x < y 调用 x.lt(y)
2._ _le_ _()
格式:
def __le__(self):
return str
特征:
触发时机:进行小于等于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义小于等于号的行为:x <= y 调用 x.le(y)
3._ _gt_ _()
格式:
def __gt__(self):
return str
特征:
触发时机:进行大于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义大于号的行为:x > y 调用 x.gt(y)
4._ _ge_ _()
格式:
def __ge__(self):
return str
特征:
触发时机:进行大于等于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义大于等于号的行为:x >= y 调用 x.ge(y)
5._ _eq_ _()
格式:
def __eq__(self):
return str
特征:
触发时机:进行等于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义大于等于号的行为:x == y 调用 x.eq(y)
6._ _ne_ _()
格式:
def __ne__(self):
return str
特征:
触发时机:进行不等于判断时自动触发
参数:2个参数第一个是self,第二个判断的第二个对象
返回值:返回值可以任意类型,推荐布尔值
作用:定义不等号的行为:x != y 调用 x.ne(y)
算术运算相关魔术方法
__add__(self, other) 定义加法的行为:+
__sub__(self, other) 定义减法的行为:-
__mul__(self, other) 定义乘法的行为:
__truediv__(self, other) 定义真除法的行为:/
__floordiv__(self, other) 定义整数除法的行为://
__mod__(self, other) 定义取模算法的行为:%
__divmod__(self, other) 定义当被 divmod() 调用时的行为
__pow__(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为
__lshift__(self, other) 定义按位左移位的行为:<<
__rshift__(self, other) 定义按位右移位的行为:>>
__and__(self, other) 定义按位与操作的行为:&
__xor__(self, other) 定义按位异或操作的行为:^
__or__(self, other) 定义按位或操作的行为:|
反运算相关魔术方法
__radd__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rsub__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rmul__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rtruediv__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rfloordiv__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rmod__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rdivmod__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rpow__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rlshift__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rrshift__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rand__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__rxor__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
__ror__(self, other) (与上方相同,当左操作数不支持相应的操作时被调用)
赋值运算相关魔术方法
__iadd__(self, other) 定义赋值加法的行为:+=
__isub__(self, other) 定义赋值减法的行为:-=
__imul__(self, other) 定义赋值乘法的行为:=
__itruediv__(self, other) 定义赋值真除法的行为:/=
__ifloordiv__(self, other) 定义赋值整数除法的行为://=
__imod__(self, other) 定义赋值取模算法的行为:%=
__ipow__(self, other[, modulo]) 定义赋值幂运算的行为:**=
__ilshift__(self, other) 定义赋值按位左移位的行为:<<=
__irshift__(self, other) 定义赋值按位右移位的行为:>>=
__iand__(self, other) 定义赋值按位与操作的行为:&=
__ixor__(self, other) 定义赋值按位异或操作的行为:^=
__ior__(self, other) 定义赋值按位或操作的行为:|=
一元运算相关魔术方法
__pos__(self) 定义正号的行为:+x
__neg__(self) 定义负号的行为:-x
__abs__(self) 定义当被 abs() 调用时的行为
__invert__(self) 定义按位求反的行为:~x
类型转换相关魔术方法 JIANG
__complex__(self) 定义当被 complex() 调用时的行为(需要返回恰当的值)
__int__(self) 定义当被 int() 调用时的行为(需要返回恰当的值)
__float__(self) 定义当被 float() 调用时的行为(需要返回恰当的值)
__round__(self[, n]) 定义当被 round() 调用时的行为(需要返回恰当的值)
__index(self)__
1. 当对象是被应用在切片表达式中时,实现整形强制转换
2. 如果你定义了一个可能在切片时用到的定制的数值型,你应该定义 index
3. 如果 index 被定义,则 int 也需要被定义,且返回相同的值
上下文管理相关魔术方法
1.\_ _enter\_ _()
2.\_ _exit\_ _()
enter(self)
1. 定义当使用 with 语句时的初始化行为
2. enter 的返回值被 with 语句的目标或者 as 后的名字绑定
exit(self, exctype, excvalue, traceback)
1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么
2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作
容器类型相关魔术方法 JIANG
__len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
__getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
__setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
__delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
__iter__(self) 定义当迭代容器中的元素的行为
__reversed__(self) 定义当被 reversed() 调用时的行为
__contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
装饰器
装饰器就是对函数或者方法或者类进行修饰
'''
#第一步:创建一个普通函数
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
#调用函数
laxi()
laxi()
'''
'''
#第二步:扩展函数的功能(不是装饰器)
#声明一个扩展函数
def decor(func):
print('求神拜佛,祝愿一切顺利')
func()#相当于调用laxi()
print('拉稀成功,烧香还愿')
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
#将laxi函数传入decor函数中
laxi = decor(laxi)
#调用函数
laxi()
laxi()
'''
'''
#第三步:扩展函数的功能(不是装饰器),使用语法糖
#声明一个扩展函数
def decor(func):
print('求神拜佛,祝愿一切顺利')
func()#相当于调用laxi()
print('拉稀成功,烧香还愿')
@decor #将laxi函数传入decor函数中#laxi = decor(laxi)
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
#调用函数
laxi()
laxi()
'''
'''
#第四步:实现基本的装饰器
def decor(func):#函数名随便写
#声明内部函数来制作完整的装饰函数
def _decor():#函数名随便写
print('求神拜佛,祝愿一切顺利')
func()#相当于调用laxi()
print('拉稀成功,烧香还愿')
return _decor
@decor#laxi = decor(laxi)
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
#调用函数
laxi()
laxi()
laxi()
laxi()
'''
#第五步:实现带有参数和返回值的哦装饰器
'''
#装饰器
def decor(func):
#这就是未来的拉稀函数
def _decor():
print('求神拜佛,祝愿一切顺利')
#调用拉稀函数时接收拉稀函数本身的返回值
result = func()#相当于调用laxi()
print('拉稀成功,烧香还愿')
#为装饰之后的函数返回一个值
return result
#返回内部函数作为未来的laxi函数
return _decor
@decor
#拉稀函数
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
return '热翔一碗'
#调用拉稀函数
jg = laxi()
print(jg)
'''
'''
#装饰器
def decor(func):
#这就是未来的拉稀函数(原函数有什么形参,这里就要有什么形参)
def _decor(who,weight):
print('求神拜佛,祝愿一切顺利')
#调用拉稀函数时接收拉稀函数本身的返回值
result = func(who,weight)#相当于调用laxi()
print('拉稀成功,烧香还愿')
#为装饰之后的函数返回一个值
return result
#返回内部函数作为未来的laxi函数
return _decor
@decor
#拉稀函数
def laxi(who,weight):
print('噗哧噗哧噗哧噗哧~~~:'+who+'拉了'+weight+'斤便便')
return '热翔一碗'
jg = laxi('马俊龙','10')
print(jg)
'''
'''
#第六步:收集参数装饰器(给装饰器内部的函数加参数)
def decor(func):
#返回未来的拉稀函数
def _decor(*who,*weight):
print('求神拜佛,祝愿一切顺利')
result = func(*who,**weight)
print('拉稀成功,烧香还愿')
return result
#返回装饰之后的函数
return _decor
@decor
def laxi(*who,**weight):
print('噗哧噗哧噗哧噗哧~~~')
print('参与拉屎的人有:',who)
print('分别拉了多少:',weight)
return '热翔一大锅!'
#调用函数
jg = laxi('马俊龙','阎瑞龙','霍云瑞','曹睿','宋笑寒',mjl = '5斤',yrl = '2斤',hyr= '1吨',cr = '10克',sxh = '便秘')
print(jg)
'''
'''
#第七步:带有参数的装饰器(给装饰器加参数)
#定义装饰器(接收装饰器参数)
def decor(arg):
#接收函数的参数
def _decor(func):
#未来的拉稀和吃饭函数的装饰
def __decorla():#未来的拉稀函数
print('求神拜佛,祝愿一切顺利')
result = func()
print('拉稀成功,烧香还愿')
return result
def __decorchi():#未来的吃饭函数
print('我要开动了~')
result = func()
print('我吃完了~')
return result
#根据装饰器的参数返回不同的装饰结果
if arg == 'la':
return __decorla
elif arg == 'chi':
return __decorchi
#返回装饰器的第一层
return _decor
@decor('la')
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
return '热翔一碗'
@decor('chi')
def chifan():
print('吧唧吧唧吧唧吧唧!~~~')
return '空碗一个'
#调用laxi
jg = laxi()
print(jg)
#调用chifan
jg = chifan()
print(jg)
'''
'''
#第八步:将类作为装饰器参数传入进来
#祝愿祈福类
class Wish:
#绑定类的方法
def before():
print('烧香拜服,祝愿一切顺利!')
#绑定类的方法
def after():
print('拉稀成功,烧香还愿~')
#装饰器
def decor(cls):
def _decor(func):
#这是未来的拉稀函数
def __decor():
cls.before()
result = func()
cls.after()
return result
#返回装饰之后的函数
return __decor
return _decor
@decor(Wish)
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
return '热翔一手'
#调用函数
jg = laxi()
print(jg)
'''
'''
#第九步:将类作为装饰器使用
class Decor:
def __init__(self,arg):
#存入对象
self.arg = arg
#此魔术方法用于接收原函数
def __call__(self,func):
#将原方法存到对象当中
self.func = func
#返回装饰之后的函数
return self.mylaxi
#装饰函数
def mylaxi(self):
print('烧香拜服,祝愿一切顺利!')
#调用原函数
result = self.func()
print('拉稀成功,烧香还愿~')
return result
@Decor(5)
def laxi():
print('噗哧噗哧噗哧噗哧~~~')
return '热翔一手'
jg = laxi()
print(jg)
'''
'''
#第十步:为类添加装饰器(单例模式)
#声明一个容器用于存放对象
obj = {}#假设存入的对象键名only 值为对象本身 {'only':对象}
def decor(cls):
#装饰器的操作
def _decor():
if 'only' in obj:
#对象已经创建
return obj['only']
else:
#对象没有创建,创建对象并返回
obj['only'] = cls()
return obj['only']
#返回装饰的操作
return _decor
#当前类只能实例化一个对象
@decor
class LiXue:
name = '小雪'
sex = '女'
age = '21岁'
def stuPy():
print('好好学习天天向上!')
#实例化第一个对象
one = LiXue()
print(one)
two = LiXue()
print(two)
three = LiXue()
print(three)
'''
#第十一步:多个装饰器嵌套
#装饰器1
def decor1(func):
def _decor1():
print('脱裤子,准备放炮')
result = func()
print('拉屎完毕,提裤子走人~')
return result
return _decor1
#装饰器2
def decor2(func):
def _decor2():
print('烧香拜佛,祝愿一切顺利!')
result = func()
print('操作成功,烧香还愿')
return result
return _decor2
@decor2
@decor1
def laxi():
print('扑哧扑哧扑哧扑哧扑哧~~')
return '热翔一大杯'
jg = laxi()
print(jg)
方法的分类
类和对象的方法一共分为三种:
实例方法/对象方法:
只有实例化对象之后才可以使用的方法,该方法的第一个形参接收的一定是对象本身!
绑定类的方法/静态方法
无需实例化,可以通过类直接调用的方法,方法中的参数既不接收对象名也不接受类。 一般方法可以独立调用,跟类中其他成员关联不大
类方法
无需实例化,可以通过类直接调用的方法,但是方法的第一个参数接收的一定是类本身,这种方法一般情况下需要借助类中其他成员操作
#包含各种方法的类
class Person:
#绑定类的方法,静态方法
@staticmethod #可以省略不写
def walk():
print('走路方法,绑定类的方法')
#非绑定类的方法 对象方法
def say(self):
print(self)
print('说话功能,非绑定类方法')
#类方法
@classmethod #必须写
def drink(cls):
print(cls)
print('喝水方法,类方法')
#调用非绑定类的方法(对象/实例方法)
tw = Person()
tw.say()
#绑定类的方法,静态方法
Person.walk()
#调用类方法
Person.drink()
抽象类
具有抽象方法的类就是抽象类。
抽象方法就是没有完成的方法。只有方法名称和参数,没有方法内容的方法。
作用:适合于领导指定开发规范及多人协作完成类。
abc abstract class 抽象类的缩写
抽象类的语法
#使用抽象类必须使用abc模块
import abc
#书写抽象类必须指定抽象类的元类 固定格式
class Human(metaclass = abc.ABCMeta):
#定义一个抽象的实例方法/非绑定类的方法
@abc.abstractmethod
def smoking(self):
pass
#定义一个抽象的类方法
@abc.abstractclassmethod
def say(cls):
pass
#定义一个抽象的静态方法/绑定类的方法
@abc.abstractstaticmethod
def cry():
pass
抽象类的特征:
1.抽象类中可以包含具体的方法也可以包含抽象方法
2.抽象类中可以包含成员属性,而且属性没有抽象不抽象之分
3.抽象类无法实例化使用.
4.抽象类只能被其他类继承使用,(唯一的用法)
5.只有子类实现了抽象类的所有抽象方法之后,该子类才可以正常实例化使用。有一个抽象方法没有实现都不可以实例化
6.抽象类的作用是指定程序开发的标准(方法名,参数等)
多态
多态,多种状态!就是一个类,根据不同的情况,相同的方法产生不同的结果。