在类中定义的函数属于绑定方法(bound method),因为用户定义的函数都有 __get__ 方法,所以依附到类上时,就相当于描述符。
示例 20-13 演示了从 面向对象专题(九)示例 20-8 里定义的 Managed 类中读取 spam 方法。
示例 20-13 方法是非覆盖型描述符

    >>> obj = Managed()
>>> obj.spam ➊
<bound method Managed.spam of <descriptorkinds.Managed object at 0x74c80c>>
>>> Managed.spam ➋
<function Managed.spam at 0x734734>
>>> obj.spam = 7 ➌
>>> obj.spam
7

❶ obj.spam 获取的是绑定方法对象。
❷ 但是 Managed.spam 获取的是函数。
❸ 如果为 obj.spam 赋值,会遮盖类属性,导致无法通过 obj 实例访问 spam 方法。

函数没有实现 __set__ 方法,因此是非覆盖型描述符,如示例 20-13 中的最后一行所示。

从示例 20-13 中还可以看出一个重要信息:obj.spam 和Managed.spam 获取的是不同的对象。与描述符一样,通过托管类访问时,函数的 __get__ 方法会返回自身的引用。
但是,通过实例访问时,函数的 __get__ 方法返回的是绑定方法对象:一种可调用的对象,里面包装着函数,并把托管实例(例如 obj)绑定给函数的第一个参数(即 self)

示例 20-14 method_is_descriptor.py:Text 类,继承自UserString 类

import collections

class Text(collections.UserString):

    def __repr__(self):
return 'Text({!r})'.format(self.data) def reverse(self):
return self[::-1]

下面来分析 Text.reverse 方法,如示例 20-15 所示。

示例 20-15 测试一个方法

    >>> word = Text('forward')
>>> word ➊
Text('forward')
>>> word.reverse() ➋
Text('drawrof')
>>> Text.reverse(Text('backward')) ➌
Text('drawkcab')
>>> type(Text.reverse), type(word.reverse) ➍
(<class 'function'>, <class 'method'>)
>>> list(map(Text.reverse, ['repaid', (10, 20, 30), Text('stressed')])) ➎
['diaper', (30, 20, 10), Text('desserts')]
>>> Text.reverse.__get__(word) ➏
<bound method Text.reverse of Text('forward')>
>>> Text.reverse.__get__(None, Text) ➐
<function Text.reverse at 0x101244e18>
>>> word.reverse ➑
<bound method Text.reverse of Text('forward')>
>>> word.reverse.__self__ ➒
Text('forward')
>>> word.reverse.__func__ is Text.reverse ➓
True

❶ Text 实例的 repr 方法返回一个类似 Text 构造方法调用的字符串,可用于创建相同的实例。

❷ reverse 方法返回反向拼写的单词。
❸ 在类上调用方法相当于调用函数。
❹ 注意类型是不同的,一个是 function,一个是 method。
❺ Text.reverse 相当于函数,甚至可以处理 Text 实例之外的其他对象。
❻ 函数都是非覆盖型描述符。在函数上调用 __get__ 方法时传入实例,得到的是绑定到那个实例上的方法。
❼ 调用函数的 __get__ 方法时,如果 instance 参数的值是 None,那么得到的是函数本身。
❽ word.reverse 表达式其实会调用Text.reverse.__get__(word),返回对应的绑定方法。
❾ 绑定方法对象有个 __self__ 属性,其值是调用这个方法的实例引用。
❿ 绑定方法的 __func__ 属性是依附在托管类上那个原始函数的引用。

绑定方法对象还有个 __call__ 方法,用于处理真正的调用过程。这个方法会调用 __func__ 属性引用的原始函数,把函数的第一个参数设为绑定方法的 __self__ 属性。这就是形参 self 的隐式绑定方式。
函数会变成绑定方法,这是 Python 语言底层使用描述符的最好例证。

python 面向对象专题(十):特殊方法 (三)__get__、__set__、__delete__ 描述符(三)方法是描述符的更多相关文章

  1. python基础----再看property、描述符(__get__,__set__,__delete__)

    一.再看property                                                                          一个静态属性property ...

  2. 描述符__get__,__set__,__delete__和析构方法__del__

    描述符__get__,__set__,__delete__ 1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一 ...

  3. 描述符__get__(),__set__(),__delete__()(三十七)

    http://www.cnblogs.com/linhaifeng/articles/6204014.html#_label12 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__ ...

  4. Python描述符(__get__,__set__,__delete__)简介

    先说定义,这里直接翻译官方英文文档: 一般来说,描述符是具有“绑定行为”的对象属性,该对象的属性访问将会被描述符协议中的方法覆盖.这些方法是__get__(),__set__(),和__delete_ ...

  5. __get__ __set__ __delete__描述符

    描述符就是一个新式类,这个类至少要实现__get__ __set__ __delete__方法中的一种class Foo: def __get__(self, instance, owner): pr ...

  6. 描述符__get__,__set__,__delete__

    描述符__get__,__set__,__delete__ # 描述符:1用来代理另外一个类的属性 # __get__():调用一个属性时,触发 # __set__():为一个属性赋值时触发 # __ ...

  7. python 面向对象专题(八):特殊方法 (一)__get__、__set__、__delete__ 描述符(一)

    https://www.cnblogs.com/flashBoxer/p/9771797.html 实现了 __get__.__set__ 或 __delete__ 方法的类是描述符.描述符的用法是, ...

  8. python 面向对象专题(十一):特殊方法 (四)__get__、__set__、__delete__ 描述符(四)描述符用法建议

    使用特性以保持简单 内置的 property 类创建的其实是覆盖型描述符,__set__ 方法和__get__ 方法都实现了,即便不定义设值方法也是如此. 特性的__set__ 方法默认抛出 Attr ...

  9. python 面向对象专题(九):特殊方法 (二)__get__、__set__、__delete__ 描述符(二)覆盖型与非覆盖型描述符对比

    前言 根据是否定义__set__ 方法,描述符可分为两大类. 实现 __set__ 方法的描述符属于覆盖型描述符,因为虽然描述符是类属性,但是实现 __set__ 方法的话,会覆盖对实例属性的赋值操作 ...

随机推荐

  1. Nginx深入浅出

    一级标题为思维导图的链接 :) 1. Nginx简介 1.1 nginx概述 说明(C10K) 程序架构(master/worker) nginx的特性 文件并发处理(异步.事件驱动)epoll / ...

  2. docker-mcr 助您全速下载 dotnet 镜像

    2018 年五月之后,微软将后续发布的所有 docker image 都推送到了 MCR (Miscrosoft Container Registry),但在中国大陆,它的速度实在是令人发指,本文将介 ...

  3. 浅谈HTTPS和HTTP

    1.HTTP和HTTPS的基本概念 HTTP:超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务端请求和应答的标准,用于WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览 ...

  4. Windows程序设计(2) -API-01 初识

    Windows 程序原理 一,CPU的保护模式和windows操作系统 [x] windows 是多任务实现 [x] 虚拟内存和 各个进程的地址空间安排:2G系统空间,2G用户空间,2G用户空间是各个 ...

  5. c++ 对vector和deque进行逆序排序问题

    1.vector vector<int> data1; 2.deque deque <int> data2; 逆序排序方式: 方式1.使用reverse函数   (内置数据类型 ...

  6. Windows下6款实用软件(强烈推荐!)

    Windows下6款实用软件 1.notepads Notepads作为一款编辑器,美观.轻量,功能强大,支持多标签页.Markdown.日常文本编辑.查看,Notepads轻松胜任,如果厌烦了Win ...

  7. 一分钟开始持续集成之旅系列之:Java + GWT

    作者:CODING - 朱增辉 前言 Google Web Toolkit(GWT)是一个开源.免费的 Web 开发框架,通过该框架,您可以使用 Java 构建复杂.高性能的 JavaScript 应 ...

  8. c语言中的c语言中realloc()函数解析

    c语言中realloc()函数解析 真是有点惭愧,这些内容本应该很早就掌握的,以前只是糊里糊涂的用,不知道在内存中具体是怎么回事,现在才弄清楚. realloc(void *__ptr, size_t ...

  9. 入门大数据---Kylin是什么?

    一.Kylin是什么? Apache Kylin是一个开源的.分布式的分析型数据仓库,提供Hadoop/Spark 上的SQL查询接口及多维度分析(OLAP)能力以支持超大规模的数据,最初由eBay开 ...

  10. Hexo快速构建个人小站-Fulid主题下添加Valine评论系统(三)

    Hexo目录: Hexo快速构建个人小站-Hexo初始化和将项目托管在Github(一) Hexo快速构建个人小站-自定义域名和自定义主题(二) 背景交代: 前面两章完成了Hexo的初始化和部分自定义 ...