设为首页 收藏本站
查看: 1074|回复: 0

[经验分享] 理解 python 的 method 和 function 兼谈 descriptor

[复制链接]

尚未签到

发表于 2017-5-5 11:50:02 | 显示全部楼层 |阅读模式
总是看到有人对 python 中的 method 和 function 之间关系的困惑,其实初学 python 时我也困惑过,不过现在自认为对这个问题还是基本清楚了 ;-)。
  我在前面写过的 selfless python 里面说过 method 本质上就是 function,这个从它们的形式上也看得出来,呵呵,而让人困惑的问题主要就是那个隐式传入的 self 参数。这其实是利用了descriptor 机制,请看代码:


>>> class Temp(object):
...   def test(self, a):
...     print self, a
...
>>> func = Temp.__dict__['test']
>>> func
<function at="" test="">
>>> func(1, 2)
1 2
</function>
由此可见 test 就是个不折不扣的函数!
>>> Temp.test
<unbound temp.test="" method="">
>>> t = Temp()
>>> t.test
<bound of="" temp.test="" method=""><__main__.Temp object at 0x00B46CD0>>
</bound></unbound>
但是这又是怎么回事了?哪里冒出个 bound/unbound method 来了?
>>> dir(func)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__ge
tattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure',
'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_na
me']

请注意其中的 __get__ 方法,这就是 descriptor 的标志(任何定义了 __get__, __set__, __delete__ 三个方法中的一个或几个的对象都是 descriptor ,这几个方法的意思大家应该能猜到了)
根据对象 attribute 的查找策略,当 t.test 时,首先根据 attribute查找策略找到这个函数对象,然后会发现它有 __get__ 属性,则调用之,并把它的返回值当作该 attribute 的值。
Temp.test 等价于 Temp.__dict__['test'].__get__(None, Temp)
t.test    等价于 Temp.__dict__['test'].__get__(t, Temp)

  其实你可以把 func.__get__ 的实现想象成下面这个等价物:


>>> class Function(object):
...     def __get__(self, obj, objtype=None):
...         import types
...         return types.MethodType(self, obj, objtype)

  到这里事情已经比较清楚了,不过还有一点可能仍然会让你感到困惑:


>>> Temp.test = test
>>> t.test(1)
<__main__.Temp object at 0x00B46E90> 1
>>> t.test = test
>>> t.test(1)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: test() takes exactly 2 arguments (1 given)
>>> t.test
<function at="" test="">
</function></stdin>
  咦?不是说 function 是 descriptor 的吗?怎么这里没有去调用它的 __get__ 方法呢?

  另外:


>>> class Meta(type):pass
...
>>> class Temp(object):
...   __metaclass__ = Meta
...
>>> class Desc(object):
...   def __get__(self, instance, type):
...     print instance, type
...
>>> desc = Desc()
>>> Meta.d = desc
>>> Meta.d
None <class __main__.meta="">
>>> Temp.d
<class __main__.temp=""> <class __main__.meta="">
>>> Temp.d = desc
>>> Temp.d
None <class __main__.temp="">
>>> t = Temp()
>>> t.d
<__main__.Temp object at 0x00B46DD0> <class __main__.temp="">
>>> t.d = desc
>>> t.d
<__main__.Desc object at 0x00B46D30>
</class></class></class></class></class>
  注意到,到最后一步 t.d 的时候也没有对 descriptor 求值。这个道理和上面那个是一样的,仔细看一下 attribute 查找策略 就可以找到答案了, descriptor 只有绑定在 type object 上才有效。

  这里我们涉及到了 python对象一种分类: type object 和 非 type object ,这两种对象在 attribute 查找过程中的待遇是不一样的。

  简单地说 type object 包括 type, type 的子类( 也就是 metaclass 了 )、 type 的实例( 也就是 class 了 )

  一般来说 type object 和 非 type object 不光在 attribute 受到不平等待遇,而且非 type object 还不能成为其它对象的基类型,想成为 metaclass 更是痴心妄想了。

  不过就像我以前说过的那样,python 中的对象本质上都是平等的,区分它们的唯一方法是它们的接口,所以我相信所谓 type object 与 非 type object 的区别也只在于接口而已。也就是说只要实现 type object 所需的接口,任何对象都可以成为 type object 。
  参考:
  How-To Guide for Descriptors
  Python Attributes and Methods

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-373445-1-1.html 上篇帖子: Python单元测试框架unittest测试过程简介 下篇帖子: 利用Python抓取和解析网页(二)补充
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表