异常
可用 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