描述符
来源:互联网 发布:JavaScript字符串分割 编辑:程序博客网 时间:2024/05/16 12:04
1. 定义
描述符是一个具有绑定行为的对象属性,其属性的访问被描述符协议方法覆写。这些方法是__get__()
、__set__()
和__delete__()
,一个对象中只要包含了这三个方法中的至少一个就称它为描述符。
2. 使用场景
常见的使用场景是:假设你有一个对象属性叫money
,你想在某些方面限制它的取值,比如限制它为int
类型,并且是非负数。你应该怎么做?
你很可能想着在类的__init__()
方法里面对money
添加这两个限制。然而这么做并不正确,因为它只是限制了money
的初始化,当你重新赋值时,这种限制并不会被执行。
有了描述符那情况就不一样了,你先将money
绑定到协议方法,然后在__set()__()
方法里面添加这两个限制。这样在你每次赋值给money
时(不管是初始化还是修改它),都会执行限制。
3. 描述符协议
Python 描述符协议 只是一种在模型中引用属性时指定将要发生事件的方法。它允许编程人员轻松、有效地管理属性访问:
__get__(self, instance, owner)__set__(self, instance, value)__delete__(self, instance)
__get__
用于访问属性。它返回属性的值,或者在所请求的属性不存在的情况下出现AttributeError
异常。__set__
将在属性分配操作中调用。不会返回任何内容。__delete__
控制删除操作。不会返回内容。
需要注意,描述符被分配给一个类,而不是实例。修改此类,会覆盖或删除描述符本身,而不是触发它的代码。
4. 创建描述符
您可以通过许多方式创建描述符:
- 创建一个类并覆盖任意一个描述符方法:
__set__
、__ get__
和__delete__
。当需要某个描述符跨多个不同的类和属性,例如类型验证,则使用该方法。 - 使用属性类型,这种方法可以更加简单、灵活地创建描述符。
- 使用属性描述符,它结合了属性类型方法和 Python 描述符。
(1)使用类方法创建描述符
使用类方法创建描述符:
class Descriptor(object): def __init__(self): self._name = '' def __get__(self, instance, owner): print "Getting: %s" % self._name return self._name def __set__(self, instance, name): print "Setting: %s" % name self._name = name.title() def __delete__(self, instance): print "Deleting: %s" %self._name del self._nameclass Person(object): name = Descriptor()
使用这些代码并查看输出:
>>> user = Person()>>> user.name = 'john smith'Setting: john smith>>> user.nameGetting: John Smith'John Smith'>>> del user.nameDeleting: John Smith
(2)使用属性类型创建描述符
通过使用 property(),可以轻松地为任意属性创建可用的描述符。创建 property()
的语法是 property(fget=None, fset=None, fdel=None, doc=None)
,其中:
get
:属性获取方法fset
:属性设置方法fdel
:属性删除方法doc
:docstring
使用属性类型创建描述符:
class Person(object): def __init__(self): self._name = '' def fget(self): print "Getting: %s" % self._name return self._name def fset(self, value): print "Setting: %s" % value self._name = value.title() def fdel(self): print "Deleting: %s" %self._name del self._name name = property(fget, fset, fdel, "I'm the property.")
使用该代码并查看输出:
>>> user = Person()>>> user.name = 'john smith'Setting: john smith>>> user.nameGetting: John Smith'John Smith'>>> del user.nameDeleting: John Smith
注意,fget
、fset
和 fdel
方法是可选的,但是如果没有指定这些方法,那么将在尝试各个操作时出现一个 AttributeError
异常。例如,声明 name
属性时,fset
被设置为 None
,然后开发人员尝试向 name
属性分配值。这时将出现一个 AttributeError
异常。
这种方法可以用于定义系统中的只读属性。
name = property(fget, None, fdel, "I'm the property")user.name = 'john smith'
输出为:
Traceback (most recent call last):File stdin, line 21, in mоduleuser.name = 'john smith'AttributeError: can't set attribute
(3)使用属性修饰符创建描述符
使用属性修饰符创建描述符:
class Person(object): def __init__(self): self._name = '' @property def name(self): print "Getting: %s" % self._name return self._name @name.setter def name(self, value): print "Setting: %s" % value self._name = value.title() @name.deleter def name(self): print ">Deleting: %s" % self._name del self._name
Ref:
https://www.ibm.com/developerworks/cn/opensource/os-pythondescriptors/
https://segmentfault.com/a/1190000006660339
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符
- 描述符表和描述符高速缓存
- HID 描述符 报告描述符
- 描述符表和描述符高速缓存
- 文件描述符与进程描述符
- 描述符表和描述符高速缓存
- 描述符表和描述符高速缓存
- 80386简介--描述段描述符表
- 描述符与Apache
- mac安装nvm
- JAVA SSH ----Hibernate核心API
- cocos2d-x:粒子系统详解 (Particle System)
- Javascript进行客户端验证(前台验证)
- Third Maximum Number
- 描述符
- Git详解之五 分布式Git
- makefile 中 $@ $^ %< 使用
- typedef void (*sighandler_t)(int);类型说明
- hibernate映射many-to-many
- 《C语言解惑》源码笔记摘录(Updating)
- kd树搜索
- 摘-标准C++中的string类的用法总结
- install and configure subversion