您的位置:首页 > 编程语言 > Python开发

python 读书笔记 (六) 异常描述符

2017-06-17 00:00 183 查看

异常

可用 sys.exc_info() 获取调用堆栈上的最后异常信息

def test():
try:
raise KeyError('KEY ERROR')
except:
print(sys.exc_info())
exc_type, exc_value, traceback = sys.exc_info()
sys.excepthook(exc_type, exc_value, traceback)

test()

断言

def test(n):
assert n > 0, 'n > 0 '
print(n)
test(-1)
AssertionError: n > 0

很简单,当条件不符时,抛出 AssertionError 异常。assert 受只读参数 __debug__ 控制,可以在启动时添加 "-O" 参数使其失效

python -O main.py

描述符

描述符协议:

def __get__(self, instance, owner)  --> value

def __get__(self, instance, owner) --> None

def __delete__(self, instance)  --> None

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

实现__get__ 和 __set__ 方法,称为 资料描述器 data descriptor

仅有 __get__方法的,称为 非资料描述器 non-data descriptor

__get__ 对 owner_class、owner_instance 访问有效

__set__、__delete__ 仅对 owner_instance 访问有效

资料描述器总是比实例字典优先。

非资料描述器可能被实例字典重写。(非资料描述器不如实例字典优先)

class RevealAccess(object):
"""A data descriptor that sets and returns values
normally and prints a message logging their access.
"""

def __init__(self, initval=None, name='var'):
self.val = initval
self.name = name

def __get__(self, obj, objtype):
print('get: Retrieving', self.name)
return self.val

def __set__(self, obj, val):
print('set: Updating', self.name)
self.val = val

class Data(object):
d = RevealAccess(10, 'var x')
y = 5

m = Data()

>>> m.d
get: Retrieving var x
10
>>> m.d = 20
set: Updating var x
>>> m.d
get: Retrieving var x
20
>>> m.y
5

obj.d 会在 obj 的字典中找 d ,如果 d 定义了 __get__ 方法,那么 d.__get__(obj) 会依据下面的优先规则被调用

对于对象来讲,方法 object.__getattribute__() 把 b.x 变成 type(b).__dict__['x'].__get__(b, type(b)) 。具体实现是依据这样的优先顺序:资料描述器优先于实例变量,实例变量优先于非资料描述器,__getattr__()方法(如果对象中包含的话)具有最低的优先级

对于类来讲,方法 type.__getattribute__() 把 B.x 变成 B.__dict__['x'].__get__(None, B)

方法和函数

>>> class Data(object):
...     def test(self): print('test')
...
>>> d = Data()
>>> d.test                                 # 只有 bound method 才会隐式传递 self。
<bound method Data.test of <__main__.Data object at 0x7f23c01b8160>>

>>> Data.test.__get__(d, Data)             # 向 __get__ 传递 instance 参数。
<bound method Data.test of <__main__.Data object at 0x7f23c01b8160>>

>>> Data.test                              # unbound method 需显式传递 self。
<function Data.test at 0x7f23bfaeeb70>

>>> Data.test.__get__(None, Data)           # instance 为 None
<function Data.test at 0x7f23bfaeeb70>

>>> bm = Data.test.__get__(d,Data)

>>> bm.__self__                               # __get__ instance 参数,也就是 self。
<__main__.Data object at 0x7f23c01b8160>

>>> bm.__call__()                             # __call__ 内部替我们传递 self !
test
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: