我正在清理一个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()