1.对象是特征(属性)和技能(方法)的结合体2.类是一系列具有相似特征和技能的对象的结合体3.类在定义阶段就会执行类体代码,生成类的名称空间
类实例化时发生的事情
1.产生一个空对象2.触发__init__方法,将空对象和需要的参数传入,为空对象的名称空间赋值
类中定义的函数本质都是绑定给对象使用的
1.不同对象就是不同绑定方法2.绑定给谁,就应该由谁来调用,谁来调用就会把谁当做第一个参数传给对应的函数
继承 URL
一种新建类的方式,子类会继承父类的属性,可以减少代码的冗余
什么是什么的关系
python2新式类:继承object类的类,以及该类的子类经典类:没有继承object的类python3类默认都继承object,所以python3中都是新式类,没有经典类
obj.mro() 可以查看类的查找顺序
属性查找
obj -> 父类 -> 父父类经典类: 深度优先新式类: 广度优先
引用父类中的属性
-
super()
专门用来引用父类的属性,依赖于继承,即使没有直接继承也会按照MRO继续查找
super(自己类名,self).__init__() 可以把super()看做是一个特殊的对象,这个对象调用__init__默认传入self, 所以往__init__()中传参时,不用写self
super严格按照mro表查找方法
-
指明道姓
这种方式与继承没有关系
class Teacher(People): def __init__(self,name,sex,age,title): People.__init__(self,name,age,sex) #调用的是__init__函数,因而需要传入self self.title=title
派生
子类可以派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找
组合
一个类中以另外一个类的对象作为数据属性,称为类的组合。组合与继承都是用来解决代码的重用性问题
组合是一种“有”的关系
封装 URL
不想外界或obj访问就可以采用封装
1.只是语法意义上的变形,不能访问,这种变形只在定义阶段发生一次 (_类名__变量名)2.封装对外不对内3.在定义阶段封装语法就已经被扫描,类内用到的被封装的变量名统一变形,所以内部可以访问
多态 URL
多态指的是一类事物有多种形态,比如动物有多种形态:猫、狗、猪
多态性的本质在于不同的类中定义有相同的方法名---衍生出鸭子类型
1.多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象,这就需要在设计时,把对象的使用方法统一成一种:例如cat、dog、pig都是动物, 但凡是动物肯定有talk方法,于是我们可以不用考虑它们三者的具体是什么类型的动物,而直接使用2.多态性的好处在于增强了程序的灵活性和可扩展性
高级用法
绑定方法与非绑定方法
1.类中定义的函数分为两大类:绑定方法和非绑定方法2.其中绑定方法又分为绑定到对象的对象方法和绑定到类的类方法。
-
classmethod
1.在类中正常定义的函数默认是绑定到对象的,而为某个函数加上装饰器@classmethod后,该函数就绑定到了类。2.类绑定方法通常用来在__init__的基础上提供额外的初始化实例的方式
-
staticmethod
为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也称为静态方法
总结绑定方法与非绑定方法的使用:若类中需要一个功能,该功能的实现代码中需要引用对象则将其定义成对象方法、需要引用类则将其定义成类方法、无需引用类或对象则将其定义成静态方法。
反射 URL
通过字符串操作类或对象的属性或方法
1.hasattr(obj, "key") 返回布尔值2.getattr(obj, "key", default=None) 3.setattr(obj, "key", value) 4.delattr(obj, "key")
元类 URL
python中一切皆对象,类也是对象
认识元类真正的目的是自定义元类控制类的创建
1.类的类就是type2.我们用class定义的类是用来产生我们自己的对象的3.内置元类type是专门用来产生class定义的类calss 类名 的时候就触发了type实例化出定义的这个类
实例化生成类的两种方法
- 方法一
class 类名:pass
-
方法二
type(类名, 基类, dict)类的三大要素: 1.类名 2.基类:默认object 3.类体代码:即类的局部名称空间(__dict__)类的名称空间里的变量在类定义阶段就生成,丢到了类的名称空间中(包括:属性变量,方法变量)补充: exec(字符串形式代码, {}, {})
自定义元类
1.控制类的创建过程2.控制类的实例化过程
metaclass
class Mymeta(type): # 控制类的创建过程 def __init__(self, calss_name, class_bases, class_dic): return super(Mymeta,self).__init__( calss_name, class_bases, class_dic) # 控制类的实例化过程 def __call__(self, *args, **kwargs) # 1.产生一个空对象 obj = self.__new__(self) # 2.实例化该对象 self.__init__(obj,*args,**kwargs) # 3.返回该对象 return obj # Foo = Mymeta('Foo', (object,), class_dic) class Foo(object, metaclass=Mymeta): pass
场景:自定义元类可以拿到类名,记录,类的名称空间,从而可以实现一些特定的功能,如往名称空间中添加键值对,判断类名是否符合首字母大写等
内置方法
双下划线的方法都是在达到某种条件时自动触发(内部自调用)
- __init__(self)
1.对象绑定方法2.实例化对象时触发场景:实例化对象时,会将 空对象和参数传给__init__
- __str__(self)
1.对象绑定方法2.打印obj时触发场景:可以自定义print(obj)打印结果注意: 必须要有返回值,且是字符串类型
- __del__(self)
1.对象绑定方法2.在对象被python系统回收之前触发,即:删除对象时场景:脚本文件运行完python系统就会回收所有的变量,包括类的对象,如果此时在类中开启了一个需要操作系统才能回收掉的资源(如:发开文件),就需要在触发__del__函数体内将打开的文件关闭
- __call__(self, *args, **kwargs)
1.对象绑定方法2.调用对象或调用类时触发,即:obj(),class 类名()3.__call__的返回值就是obj注意: class 类名() 时,触发的是元类中的__call__发生了三件事: 1). 调用object.__new__ 得到一个空对象obj obj=self.__new__(self) 2). 调用obj.__init__,将空对象和参数传进去 self.__init__(obj, *args, **kwargs) 3). 将obj return出来 return obj场景: 用来自定义类的创建过程
- __doc__
类名.__doc__ 可以查看类中写的文档注释
- __new__(self)
类加括号时,用来产生一个空对象的
单例模式 URL