python中描述器有哪些应用,在python中使用广泛,pytho中的方法,实例犯法,类方法,静态方法,这些方法都是以非数据描述器实现的
非数据描述器
现在就改成3000了,但是在类的字典里没改动,本质上还是非数据描述器
property实际上是数据描述器,阻止你去进行修改,因为你修改了就跑到set里去了,set不允许,就直接抛出异常
要修改,没提供这个属性的setattr就抛出个异常不能够去修改这个属性
propert发现你要覆盖,而且没setattr,背后的数据描述器,就会抛出异常,看起来像,实例不能覆盖属性的行为,
python中的方法(包括staticmethod和classmethod)都实现为非数据描述器,覆盖是覆盖了,但是优先使用实例的字典,
propert是数据描述器,这个d跟数据描述器挂钩,要把装饰器装饰成这个样子
这些你都感觉不是描述器,但是本质上就是描述器
这几个装饰器先这么写
描述器需要2个类,
写等价式,类(xx)就是一个init,一个类送一个 参数进去等于类的实例化,类实例化后,返回该类的实例,foo最终就不是函数了
x=B()类属性等于一个类的实例
foo=staticmethod()foo属性和另一个类的实例关联起来
本质上式相同的,唯一缺的是刚才里面实现的时候get和set
这里面实现了get和set
非数据描述器只需要搞定,get即可
现在是变成类属性由staticmethod来完成,装饰器来完成等价,这样的等价一摆,就是描述器
暂时不需要,使用下面的东西
右边相当于类的实例赋值给一个类属性,一个方法,类的标识符,是类的属性
使用A的实例,静态的直接使用,可以不传参
a.foo会触发描述器的get方法
拿到这个值,des()能有括号,说明是可以调用的
提示第22行处理出现异常
写这一行的时候已经跑到这里了,原因就是内部确实是一个非数据描述器
第一个参数是staticmethod对象,用a.foo是A的实例来调用的,实例就是A,owner是A的类
最后des()返回的应该还是foo函数
通过这个装饰器强行把self扔掉
用@classmethod依然是非数据描述器,也应该定义这样的东西
classmethod,等价几乎一样,foo=classmthod(foo),这个类属性定义又关联到实例上去了,get,又是一个非数据描述器
如果bar()就这么写就好了,但是bar(cls)就需要进行修改
这两种调用方式
先不看括号,按照描述器的定义,用实例还是类访问都会到get方法里去
这个owner其实就是A,调用bar(cls),其实就是fn(owner)
现在就可以了
这里跟property有类似的能力,把一个方法改成一个属性,这里通过classmethod,把类方法改成属性用
如果在后面加括号就不行了。因为bar返回none,none(),是会报错的
一个函数有多个参数,把这些参数固定下来后,下回调用变成一个无参函数
**用functools固定参数,partial(偏袒,)
owner属主的类,
**
返回了一个固定参数的新函数
参数固定了,调用的时候一个()就可以了
现在用偏函数就全部调用成功了
实际上标准库写的也不多,不需要字典,重新定义了属性__func__
对等价以及对类来作为装饰器的概念,用类的装饰器还是用函数的装饰器都不该是问题
拿到一个参数注解的东西,以前是装饰器来实现,现在能不能做类型的检查
实例传参的时候才能进行检查,得有数据才能进行检查
检查不通过 raise typeerro即可
传的数据挨个检查
在初始化的时候就调用
现在就类型错误
装饰器是用到inspect的,但是比较麻烦
是否可以用描述器来做,说到底 要一个类属性,
如果不写set就是非数据描述器,就不用这个了
这时候就存下来了
构建出两个类的实例,两个实例有了,这两个类属性就有了,有了get set就变成数据描述器了,数据描述器的优先级是高于实例的属性的
tom传入的参数最终到get,set
下面就可以按照之前 方式写,value现在是可以拿到值的
如果不是就没什么可说的,直接raise typeerror,类型错误
如果不是就setattr
看看在p1.__dict__上到底有什么
提示递归调用了这里递归调用了,相当于对实例属性又做,self.name
把值放进去,这样就可以,用instance.dict
要拿数据该如何
名字和年龄都拿到了
能否这么写,这样又是自己调用自己就递归了
写self行不行。提示keyerror
打印字典看看
现在试试把数据存到实例上去,每一个都是实例,各存各的,不影响
这个数据就有保存到instance上,instance就是person的实例,也可以保存到self,这个self就是typecheck实例的self,绑定的各是各的实例的,不会互相干扰的
这里用到了了数据描述器,可以用来做数据的检测
从这里抛出异常说明对的,这样就完成了类型的检查
数据描述器写法就是set进去,get出来要对应起来
现在这样不怎么好看,这个叫硬编码,写死了
可以把一个类当做callable看,函数能不能看inspect
这样就拿到了签名
能否写一个装饰器,把下面的东西提取出来
把一个cls当做参数提上来,下面要做的就是insepect.signature
name是字符串,param是参数类型
annotation注解
signature签名
param.annotation!=param.empty说明做了参数注解
相当于给cls定义一个name和age属性,装饰器一加,增加 了两个类属性上去跟某一个描述器关联起来,跟描述器的实例对象关联起来
第一种是吧原来的硬编码变成非侵入式代码,增加一种能力为它提供了类属性,而这些类属性正好是描述器对象,这个描述器又正好是数据描述器,现在如果有个实例,对实例属性的进行修改和访问都跑到描述器来
现在的代码,就存到了typecheck这里的实例来
return cls,现在person就等于person,添加两个属性,等于之前写的为cls添加一个大写name
执行成功
这个字典空的,说明数据都存到每个类属性上了
就是typecheck有两个实例
能不能把这个函数装饰器改成类装饰器
类装饰器,把下面类放到里面,一定要有init方法,(self,cls),但是init方法只能return none
cls就需要存下来
实例加()为可调用对象,需要加call方法
person实例等着赋值给p1
实例化方法创建了一个实例赋值给p1,但是其实这个person和原来的person有所不同
假person,利用可调用对象执行后,得到的实例确正好是person的实例
得到的person实例调用dict,么有问题,现在调还是空的,然后person的实例调用name和age,回到描述器上
这种也是硬编码
描述器只要把两个类型搞清楚,必须有一个类属性来等于某一个描述器对象,剩下的无非就是数据描述器,和非数据描述器,谁先谁后
这几天学了hash,相等什么概念,容器长度,布尔,布尔和长度有点关系。,空的容器等价false
上下文管理,资源申请和释放,实例化初始化以及析构跟上下文管理之间的差异
反射如何使用,比如可调用对象,看似一小点,用处很大,尤其是getattribute,getattr,这两个表现和你想的并不一样,一个是只要属性访问都走getattribute,一个是只要属性找不到,抛出异常,就归getattr管
这些就相当于是个框架按照你的意图去使用
如何实现数据描述器