我在一个开源项目中遇到了这样的事情。修改实例属性的方法返回对该实例的引用。这种构造的目的是什么?
class Foo(object):
def __init__(self):
self.myattr = 0
def bar(self):
self.myattr += 1
return self
我在一个开源项目中遇到了这样的事情。修改实例属性的方法返回对该实例的引用。这种构造的目的是什么?
class Foo(object):
def __init__(self):
self.myattr = 0
def bar(self):
self.myattr += 1
return self
Answers:
这是允许链接。
例如:
var Car = function () {
return {
gas : 0,
miles : 0,
drive : function (d) {
this.miles += d;
this.gas -= d;
return this;
},
fill : function (g) {
this.gas += g;
return this;
},
};
}
现在您可以说:
var c = Car();
c.fill(100).drive(50);
c.miles => 50;
c.gas => 50;
正如@Lie Ryan和@Frank Shearar提到的那样,这被称为“流畅的界面”,但是这种模式已经存在了很长时间了。
该模式的有争议的部分是,在OO中,您具有可变状态,因此void方法具有一种隐含的返回值this
-即,具有更新状态的对象就是该返回值的一种。
因此,在具有可变状态的OO语言中,这两个或多或少是等效的:
a.doA()
a.doB()
a.doC()
...相对于
a.doA().doB().doC()
因此,我听说过去的人们会拒绝流畅的界面,因为他们喜欢第一种形式。我听说过的“流畅接口”的另一个名字是“火车残骸”;)
我之所以说“差不多”,是因为流畅的界面会增加皱纹。他们不必“退货”。他们可以“重获新生”。这是在OO中获得不可变对象的一种方式。
所以你可以有一个A类做(伪代码)
function doA():
return new A(value + 1)
function doB():
return new A(value * 2)
function doC():
return new A(sqrt(value))
现在,每个方法都返回一个全新的对象,而初始对象保持不变。那是一种无需更改代码即可进入不可变对象的方法。
new(...)
,那将会泄漏内存。
__init__
反复调用也会带来开销。
大多数语言都知道“返回自我”的习惯用法,如果不在一行中使用它,则忽略它。但是值得注意的是,在Python中,函数None
默认返回。
当我在CS学校我的教练做了一个巨大的大约函数,过程,程序和方法之间的差别交易; 机械铅笔在我手中变得很热,从而解决了许多有关抽筋的论文问题。
可以这么说,返回self是设计类方法的确定的OO方法,但是Python允许多个返回值,元组,列表,对象,基元或None。
正如他们所说,链接只是将最后一个操作的答案放到下一个操作中,Python的运行时可以优化这种操作。列表推导是其内置形式。(很强大!)
因此,在Python中,每个方法或函数都返回值并不重要,这就是为什么默认值为None的原因。
有一种流派认为,程序中的每个动作都应将其成功,失败或结果报告给调用上下文或对象,但是在这里没有谈论DOD ADA要求。如果您需要从方法中获取反馈,请继续执行或不执行,但请尝试保持一致。
如果某个方法可能失败,则应返回成功或失败或引发要处理的异常。
一个警告是,如果您使用return self惯用语,Python将允许您将所有方法分配给变量,并且您可能会认为实际上是在获取对象时正在获取数据结果或列表。
当您尝试执行此操作时,类型限制语言会尖叫,大喊和打断,但解释型语言(Python,Lua,Lisp)更具动态性。
在Smalltalk中,每个未显式返回内容的方法都具有隐式的“返回自身”。
这是因为(a)使每个方法都返回某些内容会使计算模型更加统一,并且(b)使方法返回self很有用。Josh K举了一个很好的例子。
Python
每个未显式返回内容的方法都有一个隐式的“返回无”。
return self
)例:
print(foo.modify1().modify2())
# instaed of
foo.modify1()
foo.modify2()
print(foo)
我认为编程社区中更流行的风格。
return self
)return
用于其他目的。