Python 类方法链式调用

5

我有一个类:

class BaseModel:

    def __init__(self):
        pass

    def read_data(self):
        df = ...
        return df

    def transform_input(self, df):
        df = ...
        return df

    def execute(self, df):
        df = ...
        return df

    def run(self):
        data = self.read_data()
        data = self.transform_input(data)
        data = self.execute(data)

如何避免这些方法彼此之间的连续调用?是否可以像这样做:
data = self.read_data().transform_input().execute()

有没有办法将这些方法链接起来,并解决在这些方法链中传递参数(数据)的问题?


这些不是类方法,而是实例方法。你可以通过 return self 轻松实现链式调用。 - Amadan
这些是类方法,不是吗?抱歉,让我更新一下问题,附上从方法返回的示例数据。 - Dariusz Krynicki
2个回答

5
这些不是类方法,而是实例方法。为了进行方法链式调用,每个方法都必须返回一个实现链中下一个方法的对象。由于所有方法都是BaseModel的实例方法,因此您需要返回BaseModel的实例(或其子类)。显然这意味着您不能返回df(因为假定df不是BaseClass的对象)。将其存储在实例中,并在链的末尾检索它。
class BaseModel:

    def __init__(self):
        pass

    def read_data(self):
        self.df = ...
        return self

    def transform_input(self):
        self.df = ...
        return self

    def execute(self):
        self.df = ...
        return self

    def run(self):
        data = self.read_data().transform_input().execute().df

关于实例方法和类方法的区别,这个回答提供了一个很好的概述。


谢谢,我一直在努力找例子。鉴于这似乎不是最常用的方法,我想知道是否认为这种逻辑是最佳实践,比如使用一个类来表示一个文件(对象),然后使用实例方法进行一系列转换。有什么想法吗? - lowercase00

1
这些是实例方法,而不是类方法。
你似乎混淆了两种对象类型。你需要回答的第一个问题是这个类是否有状态。如果它有状态,那么你的数据通常会成为对象本身的一部分,在这种情况下,方法链非常直接。你只需从你的方法中返回self并链接即可。
class BaseModel:

    def __init__(self, data):
        self.data = data

    @classmethod
    def read_data(cls):
        data = #Some data read from somewhere
        return cls(data)

    def transform_input(self):
        #Transform your data
        return self

    def execute(self):
        #Do Something with data
        return self

my_object = BaseModel().transform_input().execute()

就我个人而言,我不喜欢方法链。

如果你需要无状态对象,那么你不能像你的示例中那样链接,但是你可以做一些其他的事情。

class BaseModel:

    def __init__(self):
        pass

    def read_data(self):
        data = #Some data read from somewhere
        return data

    def transform_input(self, data):
        #Transform your data
        return data

    def execute(self, data):
        #Do Something with data
        return data

my_object = BaseModel()
data = my_object.execute(my_object.transform_data(my_object.read_data()))

我也觉得这难以阅读,但这是无状态编程的实现方式。
我个人认为,每行分别调用方法更易读。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接