在Python中样式化长链

13 投票
5 回答
2726 浏览
提问于 2025-04-17 10:00

我写了一个基于“链”的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()
)

替代解决方案:分成独立的语句

根据语法来看,关于每个方法调用返回的值,有两种可能的选择:

  1. 每个方法(可能除了die(),因为它的结果没有被使用)返回的是修改后的实例(就是调用它的那个实例)。
  2. 每个方法(同样,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'

撰写回答