将对象方法与Initializer一起使用(同一行)



我正在清理一个python对象类,主要关注对象是如何创建的。__init__方法创建了一个几乎需要立即填充的空字典。但这不应该发生在__init__中,因为使用的方法会有很大的差异。这里有一个例子:

class Storage:
    def __init__(self):
        self.data = {}
    def fill_1(self):
        self.data['solo'] = 'all alone'
    def fill_2(self, buddy, bff):
        self.data['buddy'] = buddy
        self.data['bff'] = bff
    def fill_3(self, that_guy, house):
        self.data[that_guy] = house

通常,我可以像这样一个接一个地打电话:

box = Storage.Storage()
box.fill_1()

然而,当我按顺序创建许多这样的对象时,这可能会让人不知所措。我的目标是将__init__方法与同一行上的一个fill方法一起使用。我试过使用下面的电话:

box = Storage.Storage().fill_1()

但这不会创建对象,而是返回None。所以我有两个问题:

我的代码是否因为该行正在调用实例方法而返回None对象?

如何创建Storage对象,然后在同一行中调用它的fill方法?

这不是您在python中经常看到的习惯用法(尽管它在许多其他语言中非常流行,尤其是javascript),但您可以通过从mutator函数返回self来实现这一点。(看起来您也缺少了实例方法的self参数)。这意味着你也可以链突变调用——Storage().fill_1().fill_2()

class Storage(object):
    def __init__(self):
        super(Storage, self).__init__()
        data = {}
    def fill_1(self):
        data['solo'] = 'all alone'
        return self
    def fill_2(self, buddy, bff):
        data['buddy'] = buddy
        data['bff'] = bff
        return self
    def fill_3(self, that_guy, house):
        data[that_guy] = house
        return self
box = Storage().fill_1()

生成备用构造函数:

class Storage(object):
    def __init__(self):
        self.data = {}
    @staticmethod
    def filled_1():
        obj = Storage()
        obj.data['solo'] = 'all alone'
        return obj
    @staticmethod
    def filled_2(self, buddy, bff):
        obj = Storage()
        obj.data['buddy'] = buddy
        obj.data['bff'] = bff
        return obj
    @staticmethod
    def filled_3(self, that_guy, house):
        obj = Storage()
        obj.data[that_guy] = house
        return obj

然后,您就不需要担心单独的创建和初始化调用,也不需要使用调用链混淆命令查询分离:

obj1 = Storage.filled_1()
obj2 = Storage.filled_2('Jenny', 'Joe')
...

从Python 3.8开始,还可以使用赋值表达式。与其他两个答案不同,这两个答案都需要修改类本身,这可以用于任何类:

(box := Storage()).fill_1()

这将创建一个新的Storage实例,将其分配给box,然后调用其fill_1()方法。它相当于:

box = Storage()
box.fill_1()

最新更新