文章目录
前言
在之前接触到的一些比较大的开源工作中,如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的装饰器语法糖。
@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
的使用花活会增添到本内容中。
文章出处登录后可见!