classmethod(function)
  1. 这里不过多说明这个builtin方法的具体用法,python的文档和help函数已经给了这个方法充足的使用说明,所以我这里要说的时关于 classmethod , property之流的注解方法背后所用的技术细节,也是python中比较难以理解的一个知识点, 那就是 python中的 描述符。
从现象开始分析
  1. class Person(object):
  2. country = 'china'
  3. def __init__(self, name):
  4. self.name = name
  5. def say(self):
  6. print self.name

这个类开始分析,首先运行如下代码

  1. me = Person('younger')
  2. Person.__dict__
  3. me.__dict__

结果为

  1. >>> Person.__dict__
  2. dict_proxy({'__module__': '__main__', 'country': 'china', 'age': 20, 'say': <function say at 0x1047e0b18>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, ' __doc__': None, '__init__': <function __init__ at 0x1047e0b90>})
  3. >>> me.__dict__
  4. {'name': 'younger'}

我们的类和实例都具有__dict__属性,这个字典中囊括了该对象中所有的属性(类也是对象)。

继续运行代码

  1. me.country

结果为

  1. >>> me.country
  2. 'china'

继续运行代码

  1. me.__dict__['country]

结果为

  1. >>> me.__dict__['country']
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. KeyError: 'country'

由此可见,当我们调用实例属性的时候,me.name和me.dict['name'] 的结果是一样的,当调用的是类属性的时候,就截然不同了,结果显而易见,当我们再调用不同的属性的时候,系统会自动做出一些判断,但是我们现在还不知道判断是怎么进行的,也不知道是什么时候进行的,这里还不做解答,再看一个关于类中方法调用的例子。

我们继续运行代码

  1. Person.say
  2. Person.__dict__['say']
  3. me.say
  4. me.__dict__['say']

运行结果为

  1. >>> Person.say
  2. <unbound method Person.say>
  3. >>> Person.__dict__['say']
  4. <function say at 0x1047e0b18>
  5. >>> p.say
  6. <bound method Person.say of <__main__.Person object at 0x10473a190>>
  7. >>> p.__dict__['say']
  8. Traceback (most recent call last):
  9. File "<stdin>", line 1, in <module>
  10. KeyError: 'say'

先不管方法有没有被绑定,先看下结果,我们再用点和__dict__访问一个方法的时候,得到的是全然不同的结果,理论上来说应该是会得到一样的结果,因为都是要再当前对象的__dict__ 中进行查找,为什么Person的返回会完全不同呢?而且就返回结果来说,Person.say返回的结果类型为 未绑定的instancemethod, 而 Person.__dict__['say'] 返回的是普通的function类型对象, 方法的返回和调用完全和与其的不一样, 这就是描述符的作用。

官方对描述符的定义是:

  1. 一个描述符, 是一个对象对某个 “绑定” 方法的描述。

用自己的话来说,就是一个类中实现一些类似于 __get__, __set__, __getattr__, __getattribute__ 的方法,然后再对属性进行各种操作的时候,这些方法将会进行类似过滤的操作,来帮助你做一些额外的工作。

拿上面的例子来说,调用一个方法有两种情况,一种是在类中调用,另一种是实例种调用,如果是对象种调用,那么对象的 __getattribute__方法会做返回 type(obj).__dict__['func'].__get__(obj, type(obj)), 如果是类在调用,那么会被返回为 cls.__dict__['func'].__get__(None, cls), 这里___getattribute__, 起到了巨大的作用,用各种get方法进行了过滤, 所以在对方法进行操作的时候,用点和__dict__进行调回会有不同的结果,这也是描述符的作用所在。

你可以写自己的描述符,来对属性的读写进行操作。

现在我们回到staticmethod这个装饰器方法上来

  1. class StaticMethod(object):
  2. "Emulate PyStaticMethod_Type() in Objects/funcobject.c
  3. def __init__(self, f):
  4. self.f = f
  5. def __get__(self, obj, objtype=None):
  6. return self.f

上面是文档种对这个方法的python模拟,实际上builtin种的方法都是c的方法,该装饰器在get的时候进行自定义操作。

举个例子

  1. >>> class E(object):
  2. def f(klass, x):
  3. return klass.__name__, x
  4. f = classmethod(f)
  5. >>> print E.f(3)
  6. ('E', 3)
  7. >>> print E().f(3)
  8. ('E', 3)

python中的builtin函数详解-第二篇的更多相关文章

  1. python中的buildin函数详解(第一篇)

    这会是很长的一个帖子,因为我打算从python最基础的东西开始,尝试去完全的掌握它,buildin中有一些常用的函数比如 abs, open, setattr, getattr, 大家都很了解他们的用 ...

  2. python中的 zip函数详解

    python中zip()函数用法举例 定义:zip([iterable, ...]) zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple ...

  3. Python中的getattr()函数详解

    最近看Dive into python第四章自省中提到getattr()函数,作为一个内建函数平时自己没怎么用过所以也不太理解这个函数的一些用法 看了下函数本身的doc getattr(object, ...

  4. python种的builtin函数详解-第三篇

    exec_stmt ::= "exec" or_expr ["in" expression ["," expression]] eval(e ...

  5. 75.Python中ORM聚合函数详解:Sum

    Sum:某个字段的总和. 1. 求图书的销售总额,示例代码如下: from django.http import HttpResponse from django.db import connecti ...

  6. 72.Python中ORM聚合函数详解:Avg,aggregate,annotate

    聚合函数: 如果你用原生SQL语句,则可以使用聚合函数提取数据.比如提取某个商品销售的数量,那么就可以使用Count,如果想要知道销售的平均价格,那么就可以使用Avg. 聚合函数是通过aggregat ...

  7. 74.Python中ORM聚合函数详解:Max,Min

    Max和Min:获取指定对象的最大值和最小值. 1. 比如:想要获取Author表中的最大的年龄和最小的年龄.示例代码如下: from django.http import HttpResponse ...

  8. 73.Python中ORM聚合函数详解:Count

    Count:用来求某个数据的个数. 在以下所有的示例中所采用的模型为: from django.db import models # 定义作者模型 class Author(models.Model) ...

  9. Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

    上一篇说的是一个简单的应用,说明JNI是怎么工作的,这一篇主要来说一下,那个本地方法sayHello的参数的说明,以及其中方法的使用 首先来看一下C++中的sayHello方法的实现: JNIEXPO ...

随机推荐

  1. POJ2286 The Rotation Game(IDA*)

    The Rotation Game Time Limit: 15000MS   Memory Limit: 150000K Total Submissions: 5691   Accepted: 19 ...

  2. bzoj1208 [HNOI2004]宠物收养所(STL,Treap)

    1208: [HNOI2004]宠物收养所 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5956  Solved: 2317[Submit][Sta ...

  3. Jenkins 七: 部署到Tomcat

    在build.xml定义了打包target之后,我们可以将打包生成的war文件直接部署到tomcat. 1. 建立Tomcat用户. 打开Tomcat安装路径下的 conf/tomcat-users. ...

  4. qconf 介绍

    转载自:http://www.tuicool.com/articles/BJfiMbr 360 如何用 QConf 搞定 2W+ 服务器的配置管理 时间 2015-06-29 09:27:47 佚名 ...

  5. CCASS四种交收指令

    CCASS 提供了4种类型的指令:ATI: Account Transfer Instruction 账户转移指令,用于本券商各个仓位上的转移STI: Stock Segregate Account ...

  6. 在asp.net中使用confirm可以分为两种:

    在asp.net中使用confirm可以分为两种: 1.没有使用ajax,confirm会引起也面刷新 2.使用了ajax,不会刷新 A.没有使用ajax,可以用StringBuilder来完成. ( ...

  7. Java学习的随笔(3)接口

    首先是一段<Java编程思想>中,对接口的解释:“interface这个关键字产生一个完全抽象的类,它根本就没有提供任何具体的实现.它允许创建者确定方法名.参数列表.返回类型,但是没有任何 ...

  8. SetupFactory +添加frm2.0工具

    网盘链接: http://pan.baidu.com/s/1c1DFRJM 带单独的添加frm2.0工具 原setupfactory文件下载地址:http://www.pc0359.cn/downin ...

  9. OpenCV 编码样式指南

    OpenCV 编码样式指南   前言 本文档是对OpenCV中代码风格的简短说明,因为OpenCV的核心库(cv,cvaux)是用C和C++编写的,所以本文档仅对用C和C++代码的编写有效.   文件 ...

  10. Appium服务器端从启动到case完成的活动分析

    此文的目的主要是通过分析Appium Server打印出来的log,加深对Appium Server所扮演角色的理解. 这整一个过程是由一个Test Case开始执行到结束,测试的对象是SDK自带的N ...