zoukankan      html  css  js  c++  java
  • python 面向对象专题(十):特殊方法 (三)__get__、__set__、__delete__ 描述符(三)方法是描述符

    在类中定义的函数属于绑定方法(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 语言底层使用描述符的最好例证。

  • 相关阅读:
    C#中char[]与string之间的转换
    Java文件操作之文件追加 Chars
    冒泡排序法的改进 Chars
    选择排序 Chars
    编译原理 Chars
    Apk反编译 Chars
    VC中常用的方法 Chars
    Node.Js入门级《培训》
    新概念系列之《Part2 Lesson 24 It could be worse》
    《CLR via C#》Part2之Chapter5 基元类型、引用类型和值类型(三)
  • 原文地址:https://www.cnblogs.com/qiu-hua/p/12938012.html
Copyright © 2011-2022 走看看