奇淫技巧实现 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
来源:极客藏源
注意:若文章头部无特殊声明,则文章为作者原创,版权归作者所有,未经允许请勿转载(默认允许)。
转载须知:若无特殊说明,本站所有文章均遵循 CC BY-NC-SA 4.0 协议发布,转载、二次创作请遵守该协议内容,并参考以下文案添加转载声明:本文转载自网站 极客藏源 的用户 @灰尘疾客 的文章 《奇淫技巧实现 Python 注册器》。本转载文发布遵循与原文相同的 CC BY-NC-SA 4.0 协议
THE END
分享
二维码
海报
奇淫技巧实现 Python 注册器
本文涉及知识点包括装饰器、类的继承等,如有需要请自行搜索,下面是本文所参考的文章: 【Python】Python的Registry机制 - 知乎 Python中的注册器模块 | Jav……
<<上一篇
下一篇>>