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中使用itertools模块中的组合函数的教程
Apr 13 Python
Python使用urllib2模块抓取HTML页面资源的实例分享
May 03 Python
分享一个简单的python读写文件脚本
Nov 25 Python
Python实现PS滤镜Fish lens图像扭曲效果示例
Jan 29 Python
Python OpenCV 直方图的计算与显示的方法示例
Feb 08 Python
python实现合并两个排序的链表
Mar 03 Python
python利用selenium进行浏览器爬虫
Apr 25 Python
PyCharm 创建指定版本的 Django(超详图解教程)
Jun 18 Python
Python搭建代理IP池实现接口设置与整体调度
Oct 27 Python
Python Pandas 转换unix时间戳方式
Dec 07 Python
Python列表切片常用操作实例解析
Mar 10 Python
Python简易开发之制作计算器
Apr 28 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
解析phpstorm + xdebug 远程断点调试
2013/06/20 PHP
PHP数据库操作之基于Mysqli的数据库操作类库
2014/04/19 PHP
php检测图片主要颜色的方法
2015/07/01 PHP
php中的explode()函数实例介绍
2019/01/18 PHP
JQuery的$命名冲突详细解析
2013/12/28 Javascript
jquery分页对象使用示例
2014/04/01 Javascript
Jquery 1.9.1源码分析系列(十二)之筛选操作
2015/12/02 Javascript
jQuery ready()和onload的加载耗时分析
2016/09/08 Javascript
在vue组件中使用axios的方法
2018/03/16 Javascript
spirngmvc js传递复杂json参数到controller的实例
2018/03/29 Javascript
npm 下载指定版本的组件方法
2018/05/17 Javascript
Nodejs实现爬虫抓取数据实例解析
2018/07/05 NodeJs
详解Vue的钩子函数(路由导航守卫、keep-alive、生命周期钩子)
2018/07/24 Javascript
微信小程序左滑删除实现代码实例
2019/09/16 Javascript
详解Vue数据驱动原理
2020/11/17 Javascript
vue form表单post请求结合Servlet实现文件上传功能
2021/01/22 Vue.js
python将秒数转化为时间格式的实例
2018/09/16 Python
python处理自动化任务之同时批量修改word里面的内容的方法
2019/08/23 Python
Python中如何将一个类方法变为多个方法
2019/12/30 Python
Python基于yield遍历多个可迭代对象
2020/03/12 Python
CSS3中的注音对齐属性ruby-align用法指南
2016/07/01 HTML / CSS
详解Html5 Canvas画线有毛边解决方法
2018/03/01 HTML / CSS
HTML5 Canvas之测试浏览器是否支持Canvas的方法
2015/01/01 HTML / CSS
美国网上花店:JustFlowers
2017/02/12 全球购物
Ever New加拿大官网:彰显女性美
2018/10/05 全球购物
您的时尚,您的生活方式:DTLR Villa
2019/12/25 全球购物
编辑硕士自荐信范文
2013/11/27 职场文书
大学毕业自我鉴定范文
2014/02/03 职场文书
森马旗舰店双十一营销方案
2014/09/29 职场文书
2014年电厂个人工作总结
2014/11/27 职场文书
停水通知
2015/04/16 职场文书
2019暑假学生安全口号
2019/06/27 职场文书
mysql获取指定时间段中所有日期或月份的语句(不设存储过程,不加表)
2021/06/18 MySQL
SpringBoot系列之MongoDB Aggregations用法详解
2022/02/12 MongoDB
python装饰器代码解析
2022/03/23 Python
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技