2019/11/25 01-反射基本概念

反射是很多语言有的概念,要理解两个概念,运行时,和编译时
静态编译语言有俩个步骤,把类型定义好,然后把代码写好,开始编译,做编译时类型检查,还有一些绑定的事情,如果发现问题,就中止编译过程
python也有编译,是把代码编译成字节码
运行时把代码交给python解释器运行的时候,这样才报错
运行时不管编译成什么样子,最后都在内存中跑你代码的过程
绝大多数靠虚拟机运行的语言都提供了反射的能力,所谓反射,就还能获得这个对象的类型信息
2019/11/25 01-反射基本概念
一个对象就像照镜子一样能够反射出它的类型信息,能够通过这个对象找出其type,class,attribute或者method的能力,称为反射或者自省
运行时获得对象的类型信息

dir所有属性是什么,getattr获得任意一个对象的某个属性

2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
这些都是获取一些类型信息
2019/11/25 01-反射基本概念
p1.x=10 python允许你动态的添加一些属性
也提供了一些其他的语法,提供了三种方法getattr,setattr,delattr,
2019/11/25 01-反射基本概念
getattr,从一个对象上,给一个name名字,拿到一个值,没有就给缺省值default2019/11/25 01-反射基本概念
看看dir里能不能拿到
2019/11/25 01-反射基本概念
这些拿到的类型都是str
2019/11/25 01-反射基本概念
从p1上拿这个属性2019/11/25 01-反射基本概念
这些方法也是属性
2019/11/25 01-反射基本概念
现在通过实例来访问的
2019/11/25 01-反射基本概念
如果p1有y这个属性,就打印一下,hasattr,返回的是布尔值2019/11/25 01-反射基本概念
现在找不到a这个属性,这个属性异常
2019/11/25 01-反射基本概念
补个缺省值none就好了
2019/11/25 01-反射基本概念
这是等价于p1.a的
2019/11/25 01-反射基本概念
这样等价于p1.b=10002019/11/25 01-反射基本概念
现在这么写,这两个是等价的
setattr,getattr,delattr可以用字符串来访问

2019/11/25 01-反射基本概念
注释掉
2019/11/25 01-反射基本概念
运行时先创建了个p1
2019/11/25 01-反射基本概念
Point是个对象,属性show本来没有,但是下面调用了,但是实例字典里已经用默认值填好了
2019/11/25 01-反射基本概念
前面返回一个函数对象,后面加括号()调用
2019/11/25 01-反射基本概念
把实例的关联到某个函数上是可以的,属性记录函数对象是允许的2019/11/25 01-反射基本概念
想一想这两个其实差不多2019/11/25 01-反射基本概念
现在该如何调用
通过属性调用的搜索方式首先调用,搜自己的字典,然后类的字典

2019/11/25 01-反射基本概念
丢东西了,需要一个必须的self2019/11/25 01-反射基本概念
补一个self就成了2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
如果非要在实例增加一个所谓的方法
2019/11/25 01-反射基本概念
也就是现在定义一个方法,想让他变成实例的方法,这个时候定义应该放在类上面去,,放在实例字典上面也可以,这东西跟实例相关,实例字典放的东西,只跟当前实例有关
不推荐这么写,除非明确知道自己在干什么
2019/11/25 01-反射基本概念
每一个装饰器装饰的不同的函数,在这里就应该一样,所以之类需要改成Point即可
2019/11/25 01-反射基本概念
每一个对象在python中,本身都可以附加属性上去,python本身并不阻止你做这个事情,可以给任何对象直接选择增加属性的方式(get/set/delattr,选择这三个,来对属性进行操作)
setattr等价于 对象.xxx属性=xxx

2019/11/25 01-反射基本概念
这三个内建函数就可以对python任意对象的属性进行操作2019/11/25 01-反射基本概念
name注意是字符串
2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
dict本身都可以通过getattr来访问
2019/11/25 01-反射基本概念
给实例增加一个方法,不会做绑定,相当于做一个函数调用,缺什么参数补什么参数2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
mixin是增强一个类,采用多继承的方式,使用mro的线性化后,让我们的mixin类往前放,让它能抢先的被找到,相当于截胡,截了你的道
删除
2019/11/25 01-反射基本概念
假设这是一个装饰器
2019/11/25 01-反射基本概念
这样写,执行到15行,这个类被改造过吗2019/11/25 01-反射基本概念
写一个装饰器
2019/11/25 01-反射基本概念
只要你的解释器从上往下走一下,定义这块就被装饰器修改掉了 2019/11/25 01-反射基本概念
有没有这条语句其实都没关系2019/11/25 01-反射基本概念
如果是用mixin,还没运行到下面的时候,这些定义其实都已经完成了
2019/11/25 01-反射基本概念
mixin和装饰器方式不一样,mixin是通过继承的方式,把一些属性和方法覆盖掉,装饰器也是在你定义的类和函数上面加了一个语法,这个语法会在你定义的地方相当于进行直接修改,原有的类和函数,已经按照你写的装饰器代码的要求进行了变化
2019/11/25 01-反射基本概念
一般都这么写
2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
这里定义的是,他是怎么个定义的时候就怎么个继承
2019/11/25 01-反射基本概念
这个是运行时想什么时候修改就什么时候修改
2019/11/25 01-反射基本概念
这里就对类的属性和方法进行增强,这个装饰器是不能对实例进行修改的
2019/11/25 01-反射基本概念
上下都是在定义的时候决定的
2019/11/25 01-反射基本概念
但是这个就不一样,可以在实例添加
2019/11/25 01-反射基本概念
这种是在定义时就已经决定了,装饰器和mixin,mixin混入的新方法,你不想要,就可以运行时用delattr直接删掉
2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
命令分发器,通过名称找对应命令来执行,可以包装成类了,借助字典来完成了
2019/11/25 01-反射基本概念
函数一般在外面定义,注册,reg给一个命令名cmd,函数fn
run,死循环,等输入命令

2019/11/25 01-反射基本概念
下面就是写函数
2019/11/25 01-反射基本概念
注册这些,比较简单自己写,可以使用setattr,
getattr找不到就返回unknown
最简单方式就还么写

2019/11/25 01-反射基本概念
是否可以写成带参装饰器,上面就需要柯里化
2019/11/25 01-反射基本概念
命名可能跟属性冲突,所以最好弄两个字典保存下2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念
这里的属性名会和原来属性名冲突,虽然看着方便,但是在里面最好再维护一个字典,这个字典可以通过setattr来进行操作,不用setattr也可以
2019/11/25 01-反射基本概念2019/11/25 01-反射基本概念