博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python描述符理解
阅读量:5333 次
发布时间:2019-06-15

本文共 3191 字,大约阅读时间需要 10 分钟。

Python中的描述符是一个相对底层的概念

descriptor

Any object which defines the methods get(), set(), or delete(). When a class attribute is a descriptor, its special binding behavior is triggered upon attribute lookup. Normally, using a.b to get, set or delete an attribute looks up the object named b in the class dictionary for a, but if b is a descriptor, the respective descriptor method gets called. Understanding descriptors is a key to a deep understanding of Python because they are the basis for many features including functions, methods, properties, class methods, static methods, and reference to super classes. For more information about descriptors’ methods, see Implementing Descriptors.

描述符

任何实现了__get__(), __set__(), 或者 __delete__()方法的对象就是描述符。一个class的属性是一个描述符的时候,对这个属性的访问会触发特定的绑定行为。一般的我们使用a.b的方式访问,修改和删除属性,它通过查找class的字典来访问属性b,当时如果b是一个描述符,那么get,set和delete相关的描述符方法会被调用。理解描述符是深入理解python的关键,因为描述符是很多特性实现的基础,比如:方法,函数,属性,类方法,静态方法还有对父类方法的引用。详细的说明请看描述符的实现。--CooMark译

- 最后总结的很好

在说描述符之前,先看一小段代码:

class Foo(object):    """docstring for Foo"""    def __init__(self, arg=''):        super(Foo, self).__init__()        self.arg = arg    def foo(self):        print(self)        print('foo:', 123)print(Foo.foo)print(Foo().foo)print(Foo.foo.__get__)# 输出# 
#
>#

主要想说的是这个__get__,他是一个method-wrapper。每次调用一个方法,其实都是调用这个__get__构造的method对象。我们定义的方法其实都是descriptor,它通过__get__控制了对相应method的访问

def __get__(self, instance, owner)Foo.foo -- Foo.__dict__['foo'].__get__(None,Foo) # 隐式传递的self是Foo class对象, 一切皆对象,class在模块级别中也有instance

下面三种方式的调用输出的结果是一样的,这个None咋来的呢?,有一点可以确认:self都是class对象实例

# 两种访问方式是一样的print(Foo.foo.__get__(Foo(), Foo)())print(Foo.__dict__['foo'].__get__(Foo(), Foo)())c = Foo()print(Foo.foo.__get__(c, Foo)())# <__main__.Foo object at 0x0032DB10># foo: 123# None# <__main__.Foo object at 0x0032DB10># foo: 123# None# <__main__.Foo object at 0x0032DB70># foo: 123# None

再说说bound method和unbound method

区分依据就是是否给method绑定了实例对象,也就是调用的时候是否会隐式传递self参数

print(Foo.foo)# 当时3.0之后不再叫unbound method,因为定义为function更贴切# 
print(Foo().foo)#
>

描述符

我们定义的属性,方法其实都是描述符,只不过我们习以为常,而没有刻意的去了解背后的机制

class Bar(object):    """docstring for Bar"""    _name = 'Mark Xiao'    def __init__(self, arg=''):        super(Bar, self).__init__()        self.arg = arg        self._name = 'CooMark'    def _get_name(self):        return self._name    def _set_name(self, value):        self._name = value    def _del_name(self):        del self._name    name = property(_get_name, _set_name, _del_name, 'description of property name')print(Bar.name)print(Bar().name)# 
# CooMark

描述符协议:

__get__(self, instance, owner) --> return value__set__(self, instance, value)__delete__(self, instance)

描述符对象以类型 (owner class) 成员的方式出现,且最少要实现一个协议方法。最常见的描述符有 property、staticmethod、classsmethod。访问描述符类型成员时,解释器会自动调用与行为相对应的协议方法。

  1. 实现 get 和 set 方法,称为 data descriptor。
  2. 仅有 get 方法的,称为 non-data descriptor。
  3. get 对 owner_class、owner_instance 访问有效。
  4. set、delete 仅对 owner_instance 访问有效。

instance method, class method, static method

实例方法bound到instance

类方法bound到class
静态方法没有绑定,仅仅是个方法

总结

描述符是一种协议,实现了相应的描述符方法便会有相应的描述符行为,property就是一个特定的描述符类型,我们可以自己实现类似的功能

转载于:https://www.cnblogs.com/wancy86/p/descriptor.html

你可能感兴趣的文章
构建自己的项目管理方案
查看>>
利用pca分析fmri的生理噪声
查看>>
div水平居中且垂直居中
查看>>
epoll使用具体解释(精髓)
查看>>
AndroidArchitecture
查看>>
安装Endnote X6,但Word插件显示的总是Endnote Web"解决办法
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
【转】javascript 中的很多有用的东西
查看>>
Android 监听返回键、HOME键
查看>>
Android ContentProvider的实现
查看>>
sqlserver 各种判断是否存在(表名、函数、存储过程等)
查看>>
Recover Binary Search Tree
查看>>
[转]IOCP--Socket IO模型终结篇
查看>>
各种正则验证
查看>>
python中numpy.r_和numpy.c_
查看>>
egret3D与2D混合开发,画布尺寸不一致的问题
查看>>
freebsd 实现 tab 命令 补全 命令 提示
查看>>
struts1和struts2的区别
查看>>
函数之匿名函数
查看>>