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译

极客学院 - 描述符

Python方法绑定——Unbound/Bound method object的一些梳理

http://www.it165.net/pro/html/201406/15171.html - 最后总结的很好

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

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__) # 输出
# <function Foo.foo at 0x00550738>
# <bound method Foo.foo of <__main__.Foo object at 0x0054DB10>>
# <method-wrapper '__get__' of function object at 0x00550738>

主要想说的是这个__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更贴切
# <function Foo.foo at 0x006406F0> print(Foo().foo)
# <bound method Foo.foo of <__main__.Foo object at 0x0063DB30>>

描述符

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

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) # <property object at 0x004FBAE0>
# 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就是一个特定的描述符类型,我们可以自己实现类似的功能

python描述符理解的更多相关文章

  1. 杂项之python描述符协议

    杂项之python描述符协议 本节内容 由来 描述符协议概念 类的静态方法及类方法实现原理 类作为装饰器使用 1. 由来 闲来无事去看了看django中的内置分页方法,发现里面用到了类作为装饰器来使用 ...

  2. python描述符(descriptor)、属性(property)、函数(类)装饰器(decorator )原理实例详解

     1.前言 Python的描述符是接触到Python核心编程中一个比较难以理解的内容,自己在学习的过程中也遇到过很多的疑惑,通过google和阅读源码,现将自己的理解和心得记录下来,也为正在为了该问题 ...

  3. 【转载】Python 描述符简介

    来源:Alex Starostin 链接:www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/ 关于Python@修饰符的文章可 ...

  4. Python描述符 (descriptor) 详解

    1.什么是描述符? python描述符是一个“绑定行为”的对象属性,在描述符协议中,它可以通过方法重写属性的访问.这些方法有 __get__(), __set__(), 和__delete__().如 ...

  5. python描述符descriptor(一)

    Python 描述符是一种创建托管属性的方法.每当一个属性被查询时,一个动作就会发生.这个动作默认是get,set或者delete.不过,有时候某个应用可能会有 更多的需求,需要你设计一些更复杂的动作 ...

  6. python描述符 descriptor

    descriptor 在python中,如果一个新式类定义了__get__, __set__, __delete__方法中的一个或者多个,那么称之为descriptor.descriptor通常用来改 ...

  7. Python描述符的使用

    Python描述符的使用 前言 作为一位python的使用者,你可能使用python有一段时间了,但是对于python中的描述符却未必使用过,接下来是对描述符使用的介绍 场景介绍 为了引入描述符的使用 ...

  8. python描述符和属性查找

    python描述符 定义 一般说来,描述符是一种访问对象属性时候的绑定行为,如果这个对象属性定义了__get__(),__set__(), and __delete__()一种或者几种,那么就称之为描 ...

  9. Iterator Protocol - Python 描述符协议

    Iterator Protocol - Python 描述符协议 先看几个有关概念, iterator 迭代器, 一个实现了无参数的 __next__ 方法, 并返回 '序列'中下一个元素,在没有更多 ...

随机推荐

  1. webpack之傻瓜式教程

    接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpack教程满天飞,但是却很难找到一个能让新人快 ...

  2. Mysql命令大全

    格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root -p,回车后提示你输 ...

  3. HIVE教程

    完整PDF下载:<HIVE简明教程> 前言 Hive是对于数据仓库进行管理和分析的工具.但是不要被“数据仓库”这个词所吓倒,数据仓库是很复杂的东西,但是如果你会SQL,就会发现Hive是那 ...

  4. ASP.NET MVC一次删除多笔记录

    批量删除数据记录,如下面的截屏: 先选中想删除的记录,然后点一下删除铵钮,系统将把选中的记录一次性删除.在此,Insus.NET不想每删除一笔记录连接一次数据库. 因此需要把选择的记录一次上传至服务器 ...

  5. 通过sails和阿里大于实现短信验证

    通过sails与阿里大于来实现注册短信验证码的发送,逻辑图如下 1.用户在客户端发送手机号给服务器,服务器接收到手机号,生成对应时间戳,随机四位数验证码 2.服务器将电话号码和验证码告诉阿里大于服务器 ...

  6. 微信小程序教程汇总

    目前市面上在内测期间出来的一些实战类教程还是很不错的,主要还是去快速学习小程序开发的整体流程,一个组件一个组件的讲的很可能微信小程序一升级,这个组件就变了,事实本就如此,谁让现在是内测呢.我们不怕,下 ...

  7. i++、++i 、i--、--i

    总结: i++ 先用后加, ++i先加后用: i--先用后减, --i先减后用: //int i = 1; //Console.WriteLine(i);//1 //Console.WriteLine ...

  8. Linux学习日记-使用EF6 Code First(四)

    一.在linux上使用EF 开发环境 VS2013+mono 3.10.0 +EF 6.1.0 先检测一下EF是不是6的 如果不是  请参阅 Linux学习日记-EF6的安装升级(三) 由于我的数据库 ...

  9. mysql 外键约束备注

    梳理mysql外键约束的知识点. 1.mysql外键约束只对InnoDb引擎有效: 2.创建外键约束如下: DROP TABLE IF EXISTS t_demo_product; CREATE TA ...

  10. html5 audio总结

    前言 html5中对音频,视频播放原生支持.最近做了一个音乐播放器,得益于快过年了,才能抽出一点时间来总结一下.总的来说,html5对audio的支持非常强大, 难怪flash要死.浏览器上装播放插件 ...