Python中用Descriptor实现类级属性(Property)详解


Posted in Python onSeptember 18, 2014

上篇文章简单介绍了python中描述器(Descriptor)的概念和使用,有心的同学估计已经Get√了该技能。本篇文章通过一个Descriptor的使用场景再次给出一个案例,让不了解情况的同学可以更容易理解。

先说说decorator

这两个单词确实是有些相似,同时在使用中也是形影不离。这也给人造成了理解上的困难,说装饰器和描述器到底是怎么回事,为什么非得用一个@符号再加上描述器才行。

很多文章也都把这俩结合着讲,我自己看完之后都会觉得很绕。其实学习一个知识点,和做项目开发一个功能是一样的。在功能拆分的时候我们都会尽量的把任务拆分的足够小,然后才分配到开发者头上。这样保证各个任务的独立性,完整性,并且易于做进度管理。在任务开发的时候也不能把你的任务都放到一个函数/接口中去做,以避免各功能间产生高耦合的状况,导致后期难以维护。

再说回到学习一个技术点,如果你总是尝试一下子就要掌握两个或多个技术点,结果可能是忙活了半天,发现还是晕头转向。

擦,好像扯远了。

说Descriptor是Descriptor, Decorator是Decorator,遇到不懂的地方,各个击破,哪里不懂点哪里。所以先说Decorator, 关键点是你要意识到这就是一个语法糖 。所谓语法糖就是让你可以用简单的方式写代码。本质上装饰器(Decorator)就是这样:

def decorator(func):

    def wrapper():

        print 'in decorator'

        func()

    return wrapper
def func():

    print 'in func'
# 把func装饰一下

func = decorator(func)  # 左边的func其实是那个wrapper, 你执行它的时候会,它会帮你执行func()

# 等同于你在定义func的时候加上@

@decorator

def func():

    print 'in func'

正题:通过Descriptor来做一个类级的Property

常见的Property是这样的:

class Foo(object):

    _name = 'the5fire'
    @property

    def name(self):

        return self._name

这中property的使用,是实例级的应用。因为只有在 foo = Foo() 之后,才可以 foo.name 。

但是如果我需要一个类级的属性应该怎么做呢,就像是 classmethod一样,不需要实例化类我就可以调用。对应的需求是这样的,定义了一个基类DBManage:

class DBManage(object):

    @classmethod

    def table_name(cls):

        return cls.__name__.lower()
    @classmethod

    def select_all(cls):

        sql = "SELECT * FROM %s""" % cls.table_name()

        # 执行这个语句的代码

        return result

这其实一个对应着数据库中某张表的基础模型,我希望其他的Model都来继承它,然后可以重用这个table_name的方法(目前还是方法)。

我只需要这么定义User模型即可:

class User(DBManage):

    pass

然后这么定义Post模型:
class Post(DBManage):

    pass

这样我如果需要查所有的User数据,只需要 User.select_all() 即可,同理Post也是如此 Post.select_all() 。但此时发现一个有点不爽的事情。那就是基类中的 cls.table_name() 这个代码,table_name看起来就是属性,却需要用调用方法的方式获取。不妥。

于是自定义了一个classproperty:

class classproperty(object):

    def __init__(self, func):

        self.func = func
    def __get__(self, instance, klass):

        return self.func(klass)

这需要这样,我在DBManage中的代码就可以改为:

class DBManage(object):

    @classproperty

    def table_name(cls):

        return cls.__name__.lower()
    @classmethod

    def select_all(cls):

        sql = "SELECT * FROM %s""" % cls.table_name  # 多么直观

这就是Descriptor另外的一个使用案例了。
可能有人或有一个小疑问:为毛你不是在sql赋值时直接 sql = "SELECT * FROM %s" % cls.__name__.lower() 。这个问题,问的非常好,原因就一个字:懒。懒得以后每次都得敲那么多代码。
Python 相关文章推荐
Python调用C/C++动态链接库的方法详解
Jul 22 Python
深入理解Python 代码优化详解
Oct 27 Python
Python线程的两种编程方式
Apr 14 Python
编写Python脚本来获取mp3文件tag信息的教程
May 04 Python
python对视频画框标记后保存的方法
Dec 07 Python
python实现AES加密与解密
Mar 28 Python
简单了解python的一些位运算技巧
Jul 13 Python
Django中提示消息messages的设置方式
Nov 15 Python
Python实现计算长方形面积(带参数函数demo)
Jan 18 Python
python创建文本文件的简单方法
Aug 30 Python
pycharm 实现复制一行的快捷键
Jan 15 Python
解决pytorch 模型复制的一些问题
Mar 03 Python
Python中的闭包总结
Sep 18 #Python
python的即时标记项目练习笔记
Sep 18 #Python
python脚本实现分析dns日志并对受访域名排行
Sep 18 #Python
python中的字典详细介绍
Sep 18 #Python
python中执行shell命令的几个方法小结
Sep 18 #Python
python处理PHP数组文本文件实例
Sep 18 #Python
Python threading多线程编程实例
Sep 18 #Python
You might like
phpBB BBcode处理的漏洞
2006/10/09 PHP
php cookie 作用范围?不要在当前页面使用你的cookie
2009/03/24 PHP
php 文章采集正则代码
2009/12/28 PHP
Yii框架使用魔术方法实现跨文件调用功能示例
2017/05/20 PHP
js 鼠标拖动对象 可让任何div实现拖动效果
2009/11/09 Javascript
改变javascript函数内部this指针指向的三种方法
2010/04/23 Javascript
详谈 Jquery Ajax异步处理Json数据.
2011/09/09 Javascript
ECMAScript 创建自己的js类库
2012/11/22 Javascript
使用JavaScript的ActiveXObject对象检测应用程序是否安装的方法
2014/04/15 Javascript
浅谈页面装载js及性能分析方法
2014/12/09 Javascript
jQuery模拟黑客帝国矩阵效果实例
2015/06/28 Javascript
理解javascript定时器中的setTimeout与setInterval
2016/02/23 Javascript
JavaScript动态添加事件之事件委托
2016/07/12 Javascript
Angular.js之作用域scope'@','=','&'实例详解
2017/02/28 Javascript
简单实现js菜单栏切换效果
2017/03/04 Javascript
用js屏蔽被http劫持的浮动广告实现方法
2017/08/10 Javascript
vue-router 组件复用问题详解
2018/01/22 Javascript
记一次webpack3升级webpack4的踩坑经历
2018/06/12 Javascript
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
在Vue 中使用Typescript的示例代码
2018/09/10 Javascript
vue中动态select的使用方法示例
2019/10/28 Javascript
使用pyecharts无法import Bar的解决方案
2020/04/23 Python
python实现解数独程序代码
2017/04/12 Python
python2 与 pyhton3的输入语句写法小结
2018/09/10 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
浅谈Python_Openpyxl使用(最全总结)
2019/09/05 Python
Python正则表达式如何匹配中文
2020/05/27 Python
给ubuntu18安装python3.7的详细教程
2020/06/08 Python
Python批量获取并保存手机号归属地和运营商的示例
2020/10/09 Python
维多利亚的秘密官方网站:Victoria’s Secret
2018/10/24 全球购物
澳大利亚领先的在线药房:Pharmacy Online(有中文站)
2020/02/22 全球购物
儿科护士自我鉴定
2013/10/14 职场文书
财务工作者先进事迹材料
2014/01/17 职场文书
领导失职检讨书
2014/02/24 职场文书
农业开发项目建议书
2014/05/16 职场文书
感恩父母主题班会
2015/08/12 职场文书