奇淫技巧实现 Python 注册器
本文涉及知识点包括装饰器、类的继承等,如有需要请自行搜索,下面是本文所参考的文章:
三篇文章中都使用了继承 dict
类,而且重写了其部分方法,但是经检验不重写也行,所以本文提供的代码略有不同。
首先看看奇淫技巧的体现版本,仅三行代码:
class Register(dict):
def __call__(self, obj):
return self.setdefault(obj.__name__, obj) if callable(obj) else lambda x: self.setdefault(obj, x)
使用方法上面的三篇文章都有介绍,简单来说就是:
# Instantiate a Register instance.
registry = Register()
# Auto register via decorator.
@registry
def test():
pass
# Add a customize name.
@registry('name')
class eman:
pass
# Manually register.
anonymous_function = lambda: print('I am a function and I have no name') # Not recommended defination.
registry('anonymous_function')(anonymous_function)
print(registry)
# {'test': , 'name': __main__.eman, '': ()>, 'anonymous_function': ()>}
细心的人可能会发现 Register
类的第三行代码中有 callable
函数用于测试传入对象是否可调用,但是这里其实有 Bug。如果哪个大聪明这么用,那 register
里可能会被传入一些不可调用的对象:
registry = Register()
registry('A')('B')
print(registry)
# {'A': 'B'}
很明显,你不能通过 register['A']()
调用该对象,因为它是 str
类型的。
所以上面这个你当我耍耍酷就行,真正要用的话,可能会害了你(注册时不会报错,等到调用时:TypeError: 'XXX' object is not callable
)。
所以还是用下面这个比较稳妥:
class Register(dict):
def __call__(self, obj):
def add_item(k, v):
if callable(v):
return self.setdefault(k, v)
else:
raise TypeError(f'{repr(type(v).__name__)} object is not callable!')
if callable(obj):
return add_item(obj.__name__, obj)
else:
return lambda x: add_item(obj, x)
阅读剩余
版权声明:
作者:灰尘疾客
链接:https://www.gkcoll.xyz/573.html
文章版权归作者所有,未经允许请勿转载。
THE END