文章目录
- 前言
- 为什么使用`Register`或`Registry`?
- `Register`机制怎么用?
- 定义`Register`
- 使用`Register`
- 使用装饰器注册模块
- 将Register实例化,使用Register
- 总结
前言
在之前接触到的一些比较大的开源工作中,如timm,detectron2,mmlab等项目,常常会遇见Register
或Registry
模块,中文称之为注册器
或注册机制
。本篇Blog梳理一下注册器模块的使用机制,以及探讨为何要使用该模块。
为什么使用Register
或Registry
?
在常见的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的装饰器语法糖。
@decoratedef func():pass#! 等价于func = decorate(func)
则使用Register
时,可以用装饰器的方法来使用,示例如下所示:
# Define Register_funcRegister_func = Register()@Register_func.registerclass 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.registerdef add(x,y): return x+y@Register_func.registerdef minus(x,y): return x-y@Register_func.registerdef multi(x,y): return x*y@Register_func.registerdef div(x,y): return x/y
使用注册模块。
operation = Register_func["add"]result = operation(1,2)print(result)
总结
以上是最最基础的Register
的使用方式,后续有更多有关Register
的使用花活会增添到本内容中。