Python进阶
1python一切皆对象
函数 类 模块 代码本身都是对象,python灵活建立在一切皆对象。
类是模板对象,用来生成实例对象
既然类是对象,那么就可以动态的修改他的属性
2:type class object的关系
type(1)--->int
type(int)--->type
type--->int--->1其他类型一样
type--->class---->obj
object是所有类的顶层基类
type本身是一个类,同时也是一个对象,type的父类是object
type(object)---->type 好像成了一个闭环?
3 魔法函数
魔法函数可以加在类里面增强类的类型
1:不能自己创建新的魔法方法,不用继承任何类,任何类里面都可以定义魔法函数,类有了魔法函数就有了一些特性。
2:不需要自己调用,python解释器会在我们使用语法或对应函数时隐式调用,你只需要在对应的类中定义即可
3:魔法函数会影响到python语法本身,还有python的内置函数
熟悉了魔法函数,设计类的时候就会更加灵活,还能看懂源码,以及人家为什么这么设计。
鸭子类型:长得像鸭子就是鸭子;在与魔法函数结合起来,python的灵魂所在
class Students: def __init__(self, stu_list): self.stus = stu_list stu = Students(["zhangsan","lisi","wangwu"]) stus = stu.stus for stu in stus: print(stu)
class Students: def __init__(self, stu_list): self.stus = stu_list def __getitem__(self, item): return self.stus[item] stus = Students(["zhangsan","lisi","wangwu"]) for stu in stus: print(stu)
加入了魔法方法__getitem__就可以直接遍历创建出来的对象,for循环去找去找getitem方法,直到抛出异常,此时还可以切片。
魔法函数加python语法,体现了python的灵活性,写起来十分的简单,只要你熟悉了魔法函数。
魔法函数详解
4:鸭子类型
看源码的时候,有的规定参数的类型是itraeble,并不是说必须是继承这个类,而是说属于这类鸭子
这里的类型指的是实现了某魔法函数的类创建的对象。
此时你可以实现一个类满足了iterable的协议就可以,那么这个类也可以传进来
对比java,参数类型是提前定义好的,这点python动态语言十分灵活。
只要在类里面定义了魔法方法,那么这个类就是一个大类别。python充分利用了鸭子类型。
数据类型上面有一个大的类型,用的是魔法方法进行的分类。
5:抽象基类
abc模块,视为java里面的接口,接口不能实例化,abc模块里面的类同样不能实例化
python是动态语言,没有变量类型一说,python中变量只是一个符号而已,可以指向任何类型的对象,所以python中没有多态的概念
可以赋值任何数据给python中的变量,而且是可以修改的。因此不需要像java那样刻意的实现多态,因为python诞生之初就是多态
动态语言没有变量类型,因此少了编译时检查错误的环境。运行起来才会发现错误,这是动态语言的共同缺陷,无法做类型检查
python崇尚鸭子类型,贯穿python的面向对象,使用类型和设计类型时应把鸭子类型放在第一位
实现约定好的魔法函数视为协议
抽象基类:1 无法实例化
2基础类设定了方法,所有继承抽象基类的类都必须覆盖里面的抽象方法
python已经有了鸭子类型的设计,为什么要有抽象基类呢,直接实现某些方法不就行了么。
场景1:检查某个类是否有某种方法,比如说别人写了一个类,里面有__len__(),但是暂时你不知道,怎么检查呢?
提供了反射即使hasattr(类名,“属性名”)按照结果判断;但是很少用反射,更多的是判断是否是某种类型,用isinstance(stu,Iterable),而非hasattr(stu,"__iter__")
所以如果没有抽象基类,就要用hasattr的方式来判断类型
场景二:强制约束某个子类必须实现某些方法
如web框架中的组件就是抽象的,子组件是满足不同需求但是接口相同的类。
总结:python已经实现了一些通用的抽象基类,让我们可以了解python的数据结构的一些接口,在collections.abc模块下
这些抽象基类里面只放一个抽象方法,每个都有一个魔法函数,用@classmethod修饰,__subclasshook__(cls,C)
isinstance(stu,Sized),Student没有继承Sizde居然能判断出是不是这个大类
每个抽象类里面都配了这么个方法,背后本质帮你检查有没有这个魔法方法名的属性,还会尝试类的继承链;而type(stu)只能显示Student,无法显示SIzed
实际使用时很少去继承抽象基类,更多的是使用鸭子类型。
更多的是使用mixin,混合模式,一个类继承多个类,但是父类不和基类有任何关联;每个mixin类只实现一个方法,功能单一;不和基类关联,不要在mixin中使用super
6:with
和try except一起使用的时候,finally中有return,except中有return,return的结果会压入栈中
最后return的是栈顶的。
with上下文管理器,涉及到两个协议__enter__和__exit__
with会调用__enter__,结束自动调用__exit__(),不一定非是操作文件的时候使用with
任何一个类都可以 with Student() as stu:
stu.say()
6.2对于函数也可以适应上下文管理器,python提供了contextlib模块,巧妙的利用了生成器的特性,yield前是enter,yield后是exit
7:array效率高于list
当明确知道存放一种数据的时候用array
import array
arrays = array.array("i") # 参数指的是那种类型
8:元类编程
type负责创建所有类
__new__(cls, *args, **kwargs):创建实例对象之前调用的逻辑
__init__(self):生成实例对象之后,对对象做的事,主要用来完善实例对象