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 连连看连接算法
Nov 22 Python
用实例解释Python中的继承和多态的概念
Apr 27 Python
python实现猜单词小游戏
May 22 Python
在python中使用requests 模拟浏览器发送请求数据的方法
Dec 26 Python
Python for循环与range函数的使用详解
Mar 23 Python
详解python的argpare和click模块小结
Mar 31 Python
Python3.5内置模块之shelve模块、xml模块、configparser模块、hashlib、hmac模块用法分析
Apr 27 Python
Python 虚拟空间的使用代码详解
Jun 10 Python
Python配置pip国内镜像源的实现
Aug 20 Python
全网最细 Python 格式化输出用法讲解(推荐)
Jan 18 Python
基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码
Feb 18 Python
Pyqt5将多个类组合在一个界面显示的完整示例
Sep 04 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去掉URL网址中带有PHPSESSID的配置方法
2014/07/08 PHP
php中socket通信机制实例详解
2015/01/03 PHP
jQuery温习篇 强大的JQuery选择器
2010/04/24 Javascript
js open() 与showModalDialog()方法使用介绍
2013/09/10 Javascript
JQuery为页面Dom元素绑定事件及解除绑定方法
2014/04/23 Javascript
Javascript学习笔记之函数篇(六) : 作用域与命名空间
2014/11/23 Javascript
nodejs实现的一个简单聊天室功能分享
2014/12/06 NodeJs
javascript 动态修改css样式方法汇总(四种方法)
2015/08/27 Javascript
解决微信浏览器Javascript无法使用window.location.reload()刷新页面
2016/06/21 Javascript
项目实践一图片上传之form表单还是base64前端图片压缩(前端图片压缩)
2016/07/28 Javascript
jQuery和JavaScript节点插入元素的方法对比
2016/11/18 Javascript
javascript深拷贝的原理与实现方法分析
2017/04/10 Javascript
基于require.js的使用(实例讲解)
2017/09/07 Javascript
详解关于微信setData回调函数中的坑
2019/02/18 Javascript
JS实现小米轮播图
2020/09/21 Javascript
VUE项目实现主题切换的多种方法
2020/11/26 Vue.js
token 机制和实现方式
2020/12/15 Javascript
[01:15:45]DOTA2上海特级锦标赛B组小组赛#1 Alliance VS Spirit第一局
2016/02/26 DOTA
全面解读Python Web开发框架Django
2014/06/30 Python
python3实现短网址和数字相互转换的方法
2015/04/28 Python
Python判断Abundant Number的方法
2015/06/15 Python
python对象及面向对象技术详解
2016/07/19 Python
Python进行数据提取的方法总结
2016/08/22 Python
一道python走迷宫算法题
2018/01/22 Python
python模仿网页版微信发送消息功能
2018/02/24 Python
Python正则表达式匹配和提取IP地址
2019/06/06 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
python Yaml、Json、Dict之间的转化
2020/10/19 Python
艺术用品:Arteza
2018/11/25 全球购物
意大利在线药房:shop-farmacia.it
2019/03/12 全球购物
美国基督教约会网站:ChristianCafe.com
2020/02/04 全球购物
写求职信有什么意义
2014/02/17 职场文书
终止劳动合同协议书
2014/04/14 职场文书
法人单位适用的授权委托书
2014/09/19 职场文书
病人慰问信范文
2015/02/15 职场文书
2015年保险公司个人工作总结
2015/05/22 职场文书