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发送邮件实例讲解(python发邮件附件可以使用email模块实现)
Dec 03 Python
用Python的pandas框架操作Excel文件中的数据教程
Mar 31 Python
在Python的Django框架中创建语言文件
Jul 27 Python
使用Python生成随机密码的示例分享
Feb 18 Python
Python作用域用法实例详解
Mar 15 Python
Python如何判断数独是否合法
Sep 08 Python
Python使用pickle模块实现序列化功能示例
Jul 13 Python
Python常用模块之requests模块用法分析
May 15 Python
Python自定义函数计算给定日期是该年第几天的方法示例
May 30 Python
Python 图像处理: 生成二维高斯分布蒙版的实例
Jul 04 Python
Python线程条件变量Condition原理解析
Jan 20 Python
python爬虫scrapy基于CrawlSpider类的全站数据爬取示例解析
Feb 20 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
解析php下载远程图片函数 可伪造来路
2013/06/25 PHP
Laravel框架实现多个视图共享相同数据的方法详解
2019/07/09 PHP
php和nginx交互实例讲解
2019/09/24 PHP
基于Jquery的标签智能验证实现代码
2010/12/27 Javascript
这段js代码得节约你多少时间
2011/12/20 Javascript
js实现touch移动触屏滑动事件
2015/04/17 Javascript
zepto中使用swipe.js制作轮播图附swipeUp,swipeDown不起效果问题
2015/08/27 Javascript
javascript实现倒计时跳转页面
2016/01/17 Javascript
JS 通过系统时间限定动态添加 select option的实例代码
2016/06/09 Javascript
JavaScript实战之菜单特效
2016/08/16 Javascript
基于bootstrap-datetimepicker.js不支持IE8的快速解决方法
2016/11/07 Javascript
微信小程序开发animation心跳动画效果
2017/08/16 Javascript
详解如何在vue-cli中使用vuex
2018/08/07 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
浅析JS中什么是自定义react数据验证组件
2018/10/19 Javascript
微信小程序实现上拉加载功能
2019/11/20 Javascript
React Native中ScrollView组件轮播图与ListView渲染列表组件用法实例分析
2020/01/06 Javascript
JavaScript实现通讯录功能
2020/12/27 Javascript
[20:30]职业巡回赛回顾
2018/08/09 DOTA
python 中的int()函数怎么用
2017/10/17 Python
利用python如何处理nc数据详解
2018/05/23 Python
Python Pandas 对列/行进行选择,增加,删除操作
2020/05/17 Python
浅谈keras保存模型中的save()和save_weights()区别
2020/05/21 Python
基于CentOS搭建Python Django环境过程解析
2020/08/24 Python
python如何实现word批量转HTML
2020/09/30 Python
python正则表达式re.match()匹配多个字符方法的实现
2021/01/27 Python
使用html5实现表格实现标题合并的实例代码
2019/05/13 HTML / CSS
char型变量中能不能存贮一个中文汉字
2015/07/08 面试题
《最大的“书”》教学反思
2014/02/14 职场文书
经理助理岗位职责
2014/03/05 职场文书
《长江之歌》教学反思
2014/04/17 职场文书
党员民主生活会个人整改措施材料
2014/09/16 职场文书
学生检讨书怎么写
2015/05/07 职场文书
复兴之路纪录片观后感
2015/06/02 职场文书
pycharm 如何查看某一函数源码的快捷键
2021/05/12 Python
Spring实现内置监听器
2021/07/09 Java/Android