在Python中样式化长链
我写了一个基于“链”的Python API,类似于jQuery。这样我就可以写:
myObject.doStuff().doMoreStuf().goRed().goBlue().die()
问题是,当链条很长的时候,我找不到保持语法简洁的方法。在JavaScript中,我可以简单地这样写:
myOjbect
.doStuf()
.doMoreStuf()
.goRed()
.goBlue()
.die()
但是Python对缩进有要求……
5 个回答
6
虽然我不太认为这样做算是“干净”的写法,但在括号里面确实可以进行一些操作:
myOjbect.doStuf(
).doMoreStuf(arg1, arg2
).goRed(
).goBlue(
).die()
不过每个人的口味不同,所以我把这个放在答案里,以便完整说明。
7
myOjbect \
.doStuf() \
.doMoreStuf() \
.goRed() \
.goBlue() \
.die()
(我为myObject
感到难过。听起来真是很痛苦。)
23
符合PEP8的解决方案:格式化代码行
其实PEP8提到:
长代码行可以通过在括号中换行来分成多行。尽量使用这种方式,而不是用反斜杠来继续代码行。记得要适当地缩进继续的那一行。
所以我想你的代码应该像这样:
(
myOjbect
.doStuf()
.doMoreStuf()
.goRed()
.goBlue()
.die()
)
替代解决方案:分成独立的语句
根据语法来看,关于每个方法调用返回的值,有两种可能的选择:
- 每个方法(可能除了
die()
,因为它的结果没有被使用)返回的是修改后的实例(就是调用它的那个实例)。 - 每个方法(同样,
die()
不需要这样做)返回的是调用它的实例的副本。
可变对象的解决方案(方法返回原始实例)
在第一种情况(返回同一个实例)中,将长代码行分成几条语句的解决方案是:
myObject.doStuf()
myObject.doMoreStuf()
myObject.goRed()
myObject.goBlue()
myObject.die()
现实世界的例子涉及可变对象:
my_stuff = []
my_stuff.append('laptop') # my_stuff == ['laptop']
my_stuff.append('jacket') # my_stuff == ['laptop', 'jacket']
my_stuff.append('apple') # my_stuff == ['laptop', 'jacket', 'apple']
(虽然list.append()
不返回任何东西,这只是为了保持一致性,并明确说明它是可变的)
不可变对象的解决方案(方法返回修改后的副本)
在第二种情况(返回副本)中,做类似事情的解决方案是:
myObject = myObject.doStuf()
myObject = myObject.doMoreStuf()
myObject = myObject.goRed()
myObject = myObject.goBlue()
myObject.die()
现实世界的例子涉及不可变对象:
name = '-Tadek-'
name = name.strip('-') # name == 'Tadek'
name = name.lower() # name == 'tadek'
name = name.replace('k', 'ck') # name == 'tadeck'