mmf阅读笔记之registry.py

詹钊
2023-12-01

=== 简介 ===

  • 功能

使用唯一的键值(keys)来标记各种信息
用于注册各种不同的类(class)

  • 导入方式
from mmf.common.registry import registry
  • 使用方式

Register a trainer:
@registry.register_trainer
Register a dataset builder:
@registry.register_builder
Register a metric:
@registry.register_metric
Register a loss:
@registry.register_loss
Register a fusion technique:
@registery.register_fusion


=== 详解 ===

  • 源码
class Registry:
    mapping = {
        # 使用 `registry.register_builder` 注册添加一个新的生成器类 (builder),其他部件(trainer/...)同理
        #mapping字典存放了各个部件对应的所有被创建的类
        "builder_name_mapping": {},
        "trainer_name_mapping": {},
        "model_name_mapping": {},
        "metric_name_mapping": {},
        "loss_name_mapping": {},
        "fusion_name_mapping": {},
        "optimizer_name_mapping": {},
        "scheduler_name_mapping": {},
        "processor_name_mapping": {},
        "encoder_name_mapping": {},
        "decoder_name_mapping": {},
        "transformer_backend_name_mapping": {},
        "state": {},
    }

    @classmethod
    def register_trainer(cls, name):
   
        #以name为key的trainer将被注册
        """
        用法
        from mmf.common.registry import registry
        from mmf.trainers.custom_trainer import CustomTrainer


            @registry.register_trainer("custom_trainer")
            class CustomTrainer():
                ...
        即trainer_name_mapping中添加了custom_trainer类
        """

        def wrap(trainer_cls):
            cls.mapping["trainer_name_mapping"][name] = trainer_cls
            return trainer_cls

        return wrap

=== 拓展 ===

  • classmethod修饰符

作用
classmethod对应的函数不需要实例化,不需要self参数
但是第一个参数需要的是自身类的cls参数

返回值
返回函数的类方法

举例

class A(object):
    bar = 1
    def func1(self):  
        print ('foo') 
    @classmethod
    def func2(cls):
        print ('func2')
        print (cls.bar)
        cls().func1()   # 调用 foo 方法
 
A.func2()               # 不需要实例化

  • 函数装饰器

作用
通过装饰器函数在不修改原函数的前提下,对函数的功能进行合理扩充

举例

#funA 作为装饰器函数
def funA(fn):
    #...
    fn() # 执行传入的fn参数
    #...
    return '...'

@funA
def funB():
    #...

等价于

def funA(fn):
    #...
    fn() # 执行传入的fn参数
    #...
    return '...'

def funB():
    #...

funB = funA(funB)

以上执行的操作为两步:

  1. B作为参数传给A()函数
  2. 将A()函数执行完成的返回值反馈给B

注意被“@函数”修饰的函数不再是原来的函数,取决于返回值
如果装饰器函数返回值是普通变量,那么被就是的函数名就变成了普通变量,如果装饰器函数返回的是一个函数的名称,那么被修饰的函数名仍然是一个函数

 类似资料: