什么是注册器
python 的 register 可以理解为一个字典,字典中存储了 class/function 的名称和内容。
注册器具有 “set item” 和 “get item” 功能,从而实现对应功能的实现和调用。
注册器工作原理
首先实现一个简单的注册器,使用 register
方法实现 “set item”,使用 get 方法实现 “get item”
class MyRegister(object):
def __init__(self):
# 注册器的本质是字典
self._name_method_map = dict()
def register(self, obj=None):
# set item
if obj != None: # 常规调用
name = obj.__name__
self._name_method_map[name] = obj
else: # 装饰器形式调用
def wrapper(func):
name = func.__name__
self._name_method_map[name] = func
return func
return wrapper
def get(self, name):
# get item
return self._name_method_map[name]
使用常规方法调用注册器注册并调用一个函数
def function1(name):
print(f'Here is function1, my name is {name}')
my_register = MyRegister()
my_register.register(function1)
my_register.get('function1')(name='ys-li')
运行结果
Here is function1, my name is ys-li
使用装饰器方法调用注册器注册一个 class 对象并调用其方法
@my_register.register() # 装饰器
class MMEditing:
def __init__(self, user_name) -> None:
self.user_name = user_name
print(f'welcome to MMEditing, {user_name}')
def evaluate(self, attitude):
print(f'{self.user_name} said that {attitude}')
mmediting = my_register.get('MMEditing')("ys-li")
mmediting.evaluate('MMEditing is useful and powerful')
运行结果
welcome to MMEditing, ys-li
ys-li said that MMEditing is useful and powerful
为什么要用注册器
- 利于扩展代码,需要增加新类的时候,可以复用之前的逻辑(向字典里添加)
- 创建实例时通过读取配置文件读取对应的参数进行创建
- 在较大的 python 项目中,维护注册器更为方便
MMEditing 中的注册器
MMEditing 中已实例化出以下注册器对象,用户可直接使用
- DATASETS:数据集注册器
- PIPELINES:pipeline注册器
- MODELS:模型注册器
- BACKBONES:主干模块注册器
- COMPONENTS:模块注册器
- LOSSES:损失函数注册器
通常使用装饰器方法进行注册,以在 PIPELINES 中注册 Resize 为例
from ..registry import PIPELINES
@PIPELINES.register_module()
class Resize:
...
非常简单,建立 class 的语句上面加一个注册器装饰语句就可以了。
注册器带来的不便如何解决
注册器有助于维护大型项目,当然也有弊端,最明显的缺点是使用门槛提高。
使用注册器之前:在 vscode 中哪里不懂点哪里(Ctrl+鼠标左键),即可跳转到对应 code 中进行学习
使用注册器之后:各种 class 都在 config 中通过字典调用,不能直接跳转了
解决方法
- GitHub
进入 MMEditing,在左上角输入目标 class 名称,在仓库中进行搜索,就可以找到定义位置了。
- VScode
点击左上角的放大镜,在输入栏输入名称即可全局搜索。
小技巧:确认目标是 class 的话可以缩小搜索范围
点击高亮的代码就可以打开对应文件位置。