简体   繁体   English

Python inheritance 和关键字 arguments

[英]Python inheritance and keyword arguments

I'm writing a wrapper for pytorch transformers.我正在为 pytorch 变压器编写一个包装器。 To keep it simple I will include a minimal example.为了简单起见,我将包含一个最小的示例。 A class Parent , that will be an abstract class for classes My_BERT(Parent) and My_GPT2(Parent) .一个 class Parent ,这将是My_BERT(Parent)My_GPT2(Parent)类的抽象 class 。 Because LM models for model_Bert and model_gpt2 are included in pytorch, they have many similar functions, thus I want to minimize code redundancy by coding otherwise identical functions in Partent .因为model_Bertmodel_gpt2的 LM 模型包含在 pytorch 中,所以它们有许多相似的功能,因此我想通过在Partent中编码其他相同的功能来最小化代码冗余。

My_bert and My_gpt2 differ basically with the model initialization, and one argument passed to model, but 99% of functions use both models in identical way. My_bertMy_gpt2与 model 初始化和一个参数传递给 model 基本不同,但 99% 的函数以相同的方式使用这两种模型。

The problem is with function "model" that accepts different arguments:问题在于接受不同 arguments 的 function“模型”:

  • for model_Bert it is defined as model(input_ids, masekd_lm_labels)对于model_Bert ,它被定义为 model(input_ids, masekd_lm_labels)
  • for model_gpt2 it is defined as model(input_ids, labels)对于model_gpt2 ,它被定义为 model(input_ids, labels)

minmal code example:最小代码示例:

class Parent():
    """ My own class that is an abstract class for My_bert and My_gpt2 """
    def __init__(self):
        pass

    def fancy_arithmetic(self, text):
        print("do_fancy_stuff_that_works_identically_for_both_models(text=text)")

    def compute_model(self, text):
        return self.model(input_ids=text, masked_lm_labels=text) #this line works for My_Bert
        #return self.model(input_ids=text, labels=text) #I'd need this line for My_gpt2

class My_bert(Parent): 
    """ My own My_bert class that is initialized with BERT pytorch 
    model (here model_bert), and uses methods from Parent """
    def __init__(self):
        self.model = model_bert()

class My_gpt2(Parent):
    """ My own My_gpt2 class that is initialized with gpt2 pytorch model (here model_gpt2), and uses methods from Parent """
    def __init__(self):
        self.model = model_gpt2()

class model_gpt2:
    """ This class mocks pytorch transformers gpt2 model, thus I'm writing just bunch of code that allows you run this example"""
    def __init__(self):
        pass

    def __call__(self,*input, **kwargs):
        return self.model( *input, **kwargs)

    def model(self, input_ids, labels):
        print("gpt2")

class model_bert:
    """ This class mocks pytorch transformers bert model"""
    def __init__(self):
        pass

    def __call__(self, *input, **kwargs):
        self.model(*input, **kwargs)

    def model(self, input_ids, masked_lm_labels):
        print("bert")


foo = My_bert()
foo.compute_model("bar")  # this works
bar = My_gpt2()
#bar.compute_model("rawr") #this does not work.

I know I can override Parent::compute_model function inside My_bert and My_gpt2 classes.我知道我可以在My_bertMy_gpt2类中覆盖Parent::compute_model function 。

BUT since both "model" methods are so similar, I wonder if there is a way to say: " I'll pass you three arguments, you can use those that you know"但是由于这两种“模型”方法非常相似,我想知道是否有一种方法可以说:“我会给你三个 arguments,你可以使用你知道的那些”

def compute_model(self, text):
    return self.model(input_ids=text, masked_lm_labels=text, labels=text) # ignore the arguments you dont know

*args and **kwargs should take care of the issue you are running into. *args**kwargs应该解决您遇到的问题。

In your code, you will modify compute_model to take the arbitrary arguments在您的代码中,您将修改compute_model以采用任意 arguments

def compute_model(self, *args, **kwargs):
    return self.model(*args, **kwargs)

Now the arguments will be defined by the model method on the different classes现在 arguments 将由不同类上的model方法定义

With this change the following should work:通过此更改,以下内容应该可以工作:

foo = My_bert()
foo.compute_model("bar", "baz")
bar = My_gpt2()
bar.compute_model("rawr", "baz")

If you are not familiar with args and kwargs, they allow you to pass arbitrary arguments to a function.如果您不熟悉 args 和 kwargs,它们允许您将任意 arguments 传递给 function。 args will take unnamed parameters and pass them in the order them are received to the function kwargs or keyword arguments takes named arguments and passed them to the correct parameter. args 将采用未命名的参数并按照将它们接收到 function kwargs 或关键字 arguments 的顺序将它们传递给名为 arguments 的参数并将它们传递给正确的参数。 So the following will also work:因此,以下内容也将起作用:

foo = My_bert()
foo.compute_model(input_ids="bar", masked_lm_labels="baz") 
bar = My_gpt2()
bar.compute_model(input_ids="rawr", labels="baz") 

Just a note the names args and kwargs are meaningless, you can name them anything, but the typical convention is args and kwargs请注意,名称 args 和 kwargs 是没有意义的,您可以将它们命名为任何名称,但典型的约定是 args 和 kwargs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM