Python中的Register(注册器)模块,Registry(注册机制)的讲解及示例

前言

在之前接触到的一些比较大的开源工作中,如timm,detectron2,mmlab等项目,常常会遇见RegisterRegistry模块,中文称之为注册器注册机制。本篇Blog梳理一下注册器模块的使用机制,以及探讨为何要使用该模块。

为什么使用RegisterRegistry

在常见的CV模型中,例如分类、检测、分割等任务中,针对一个模型,(例如Faster-RCNN),可能在一个Head的基础上换多个Backbone(例如ResNet,DenseNet等)。或者说针对一套模型,可能会跑多个数据集。最简单的实现方式就是有多套代码,每套代码仅在Backbone部分或数据加载部分有差异。但是这样而言对于一个大型项目来说会过于繁琐,不够简洁,每新增一个新的模型,需要手动维护很多代码。因此,许多项目都使用了Register注册器机制。

使用Register注册器机制可以让项目易于扩展,当产品增加某个功能需要增加一些新函数或者类时,它可以保证我们可以复用之前的逻辑。

Register机制怎么用?

定义Register

首先我们需要定义一个注册器的Class,我们这里直接引用Python中的注册器模块的代码,代码示例如下所示:

class Register:
	
    def __init__(self, registry_name): 
    	# 可以将Register视为一个`dict`
        self._dict = {}
        self._name = registry_name

    def __setitem__(self, key, value):
        if not callable(value):
            raise Exception(f"Value of a Registry must be a callable!\nValue: {value}")
        if key is None:
            key = value.__name__
        if key in self._dict:
            logging.warning("Key %s already in registry %s." % (key, self._name))
        self._dict[key] = value

    def register(self, target):
        """Decorator to register a function or class."""
		# 关键函数,可以作为装饰器,注册一个函数或者一个类别。
        def add(key, value):
            self[key] = value
            return value

        if callable(target):
            # @reg.register
            return add(None, target)
        # @reg.register('alias')
        return lambda x: add(target, x)

    def __getitem__(self, key):
        return self._dict[key]

    def __contains__(self, key):
        return key in self._dict

    def keys(self):
        """key"""
        return self._dict.keys()

使用Register

使用装饰器注册模块

首先补充一个知识点,@是python的装饰器语法糖。

@decorate
def func():
	pass
#! 等价于

func = decorate(func)

则使用Register时,可以用装饰器的方法来使用,示例如下所示:

# Define Register_func
Register_func = Register()
@Register_func.register
class Modle1:

等价于Register_func.register(Model1),最终执行的是add(None, Model1)

@Register_func.register("model_one")
class Model1:

等价于Register_func.register("model_one")(Model1),最终执行的是add("model_one", Model_1)

简而言之,Register类提供了方便的注册器来对模块进行注册。

将Register实例化,使用Register

为了更好的展示使用方式,我们定义一些简单的函数,例如加减乘除等函数,为了省略重复代码,我们就直接给他们用Register注册了。
代码示例如下所示:

注册Register。

Register_func = Register("Register_func")    

@Register_func.register
def add(x,y):
    return x+y

@Register_func.register
def minus(x,y):
    return x-y

@Register_func.register
def multi(x,y):
    return x*y

@Register_func.register
def div(x,y):
    return x/y

使用注册模块。

operation = Register_func["add"]
result = operation(1,2)
print(result)

总结

以上是最最基础的Register的使用方式,后续有更多有关Register的使用花活会增添到本内容中。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年3月8日 下午10:27
下一篇 2023年3月8日 下午10:28

相关推荐