102 lines
2.3 KiB
Python
102 lines
2.3 KiB
Python
#!/usr/bin/env python
|
||
# -*- encoding: utf-8 -*-
|
||
"""
|
||
Topic: 混入类
|
||
Desc : 如果单独使用Minxin类没有任何意义,但是当利用多继承和其他类配合后就有神奇效果了。
|
||
Mixin也是多继承的主要用途。
|
||
"""
|
||
|
||
|
||
class LoggedMappingMixin:
|
||
"""
|
||
Add logging to get/set/delete operations for debugging.
|
||
"""
|
||
__slots__ = () # 混入类都没有实例变量,因为直接实例化混入类没有任何意义
|
||
|
||
def __getitem__(self, key):
|
||
print('Getting ' + str(key))
|
||
return super().__getitem__(key)
|
||
|
||
def __setitem__(self, key, value):
|
||
print('Setting {} = {!r}'.format(key, value))
|
||
return super().__setitem__(key, value)
|
||
|
||
def __delitem__(self, key):
|
||
print('Deleting ' + str(key))
|
||
return super().__delitem__(key)
|
||
|
||
|
||
class SetOnceMappingMixin:
|
||
'''
|
||
Only allow a key to be set once.
|
||
'''
|
||
__slots__ = ()
|
||
|
||
def __setitem__(self, key, value):
|
||
if key in self:
|
||
raise KeyError(str(key) + ' already set')
|
||
return super().__setitem__(key, value)
|
||
|
||
|
||
class StringKeysMappingMixin:
|
||
'''
|
||
Restrict keys to strings only
|
||
'''
|
||
__slots__ = ()
|
||
|
||
def __setitem__(self, key, value):
|
||
if not isinstance(key, str):
|
||
raise TypeError('keys must be strings')
|
||
return super().__setitem__(key, value)
|
||
|
||
|
||
class LoggedDict(LoggedMappingMixin, dict):
|
||
pass
|
||
|
||
|
||
d = LoggedDict()
|
||
d['x'] = 23
|
||
print(d['x'])
|
||
del d['x']
|
||
|
||
from collections import defaultdict
|
||
|
||
|
||
class SetOnceDefaultDict(SetOnceMappingMixin, defaultdict):
|
||
pass
|
||
|
||
|
||
d = SetOnceDefaultDict(list)
|
||
d['x'].append(2)
|
||
d['x'].append(3)
|
||
# d['x'] = 23 # KeyError: 'x already set'
|
||
|
||
|
||
def LoggedMapping(cls):
|
||
"""第二种方式:使用类装饰器"""
|
||
cls_getitem = cls.__getitem__
|
||
cls_setitem = cls.__setitem__
|
||
cls_delitem = cls.__delitem__
|
||
|
||
def __getitem__(self, key):
|
||
print('Getting ' + str(key))
|
||
return cls_getitem(self, key)
|
||
|
||
def __setitem__(self, key, value):
|
||
print('Setting {} = {!r}'.format(key, value))
|
||
return cls_setitem(self, key, value)
|
||
|
||
def __delitem__(self, key):
|
||
print('Deleting ' + str(key))
|
||
return cls_delitem(self, key)
|
||
|
||
cls.__getitem__ = __getitem__
|
||
cls.__setitem__ = __setitem__
|
||
cls.__delitem__ = __delitem__
|
||
return cls
|
||
|
||
|
||
@LoggedMapping
|
||
class LoggedDict(dict):
|
||
pass
|