假装Python高手,你真的懂属性描述符类!

Python学了好几年,发现功力还是那样,很多同学经常这样抱怨!都说Python入门容易,精通难,确实是这样的,每当我们打开一些牛逼的源码框架,进去看窥探大牛的源码,比如Python里面非常著名的Django和Flask里面的源码,发现跟天书一样

大神都大量的使用了一些元编程,魔法函数,以及类的一些深入特性,做了很多封装。最近菜鸟哥准备写一个系列,假装Python高手系列,欢迎大家来指导工作。


9bd6cb3a0dd3b8f42509c9c3e5e3517f.png

今天我们写一下入门的篇,什么是描述符类!

1.问题的来源

所有的高级技巧其实都是为了让代码更简洁,更好复用,更好扩展,就是为了这个道,而产生出很多法,设计出什么招式来解决。比如我们在实际的项目中会要设计一个Student类,类似这样的:

d3e4bf35a626c13f8c458d88e5dea6f2.png

这个类的接口有两个参数,一个是输入学生的年龄(age),一个是输入学生的成绩(score)。但是细细想,我们录入年龄和成绩的时候,需要判断是否是整数而且会有一定的范围,就是入口参数检测

于是我们就会把代码复杂到这样:

a32917225bc2d7f8b50d9b45a64e464d.png

我们要检查年龄是否是int and 大于0,要检查score是否为int and 在0-100之间。这样的检查非常啰嗦很冗余,如果我们这个系统有10个类似的这样的参数都这检查,是不是非常麻烦,代码越写越长,全部挤在一起,又重复有不好debug,肿怎么办?

2.如何解决

我先来看一下大师是怎么处理这样的问题的,尤其是写框架的大师,比如django中设计model的时候我们会碰到很多类似的这样的模型参数:

16e11663fabdecd31cebdbdb70bf3d3a.png

这个是我们从django里面随便拿出一段model设计的代码,oam创建模型的时候,我们有age/phone这样的small int的参数,就会有用一个SmalIntergerField类型去进行封装检查。

而这个SmallIntergerField就是描述符的类,就是把一个类作为一个类属性进行封装。我们回到上面的student这个类,进一步的拆解。

我们希望我们的类还是设计的很简单,但是在self.age=age进行赋值的时候,能自动的帮我进行检查,这个时候就是类描述符上场了。

class Student:
   def __init__(self,age,score):
        self.age=age
        self.score=score

3.什么是属性描述符类

就是如果一个类里面带__get__,__set__,__del__魔法函数一个或者多个的类就是描述符类。他会有特殊的用法,比如我们设计一个IntField这样的类:

d2039e72c47350c9b2ca37f253358ade.png

那么这样的描述符类有什么特殊的用处的,其实这就是假装Python高手的精华地方,我们需要把这个描述符类作为一个属性封装到Student类里面。

4.进阶高手,设计属性描述符类

经过前面的讲解,大家知道了问题所在,已经什么是描述符类,这样知识要串起来才有用,那么如何利用把描述符类封装到Student类里面来帮助我们解决上面的痛点呢。其实很简单,看代码:

9d1aa8b7c1fe3317c59347d6f9764a4d.png

我们可以很清楚的看到,我们在Student类里面设计了一个类属性age,它其实是一个描述符的类,当我们在init里面赋值给self.age=age的时候,就会自动触发调用__set__函数,而这个里面就可以帮助我们进行参数检测。

我已经打印了set传入参数,比如instance其实就是我们传入的student这个对象也就是(self),而value其实就是age的值。既然这两个最重要的东西都传进来了,那么我们就可以在set函数里面随意的添加我们的业务逻辑检查了(比如一开始说到的参数预检测)

5ecd0ac2f450698a18f8963d6ec7ad55.png

这里的设计有点复杂,我们分几个方面讲:

1).如果传入的value进行类型检查,如果不是int ,报错

2).如果传入的value是年龄并且<0,报错

3).如果传入的value是成绩并且<0 或者>100,报错

4).如果以上都不满足,说明我们输入的参数是正确的,我们需要把这个属性添加到我们的类里面,这样就可以方便的s.age进行调用

3aa7165061d650725eb0916c4e051ee6.png

这样的话,我们在外边使用这个student对象的时候,可以非常简单和轻松,而复杂的逻辑都封装到了IntField里面,如果我们代码要扩展比如增加一些类似的int参数,代码只要增加一行,是不是感觉自己Python高手了一点。

好,今天的分享就到这里,我们的假装Python系列才刚刚开始,欢迎在留言区指导工作,你品,你细品。

 
 
 
 
 
 
 
 
 
 

推荐阅读:

入门: 最全的零基础学Python的问题  | 零基础学了8个月的Python  | 实战项目 |学Python就是这条捷径

量化: 定投基金到底能赚多少钱?  | 我用Python对去年800只基金的数据分析

干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 |   从万众期待到口碑扑街!唐探3令人失望  | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影

趣味:弹球游戏  | 九宫格  | 漂亮的花 | 两百行Python《天天酷跑》游戏!

AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影

小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!|  再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!

年度爆款文案

 
 
 
 
 
 
 
 
 
 
 
 

 
 
 
 
 
 
点阅读原文,领AI全套资料!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值