在Python中使用样式化长链

Ran*_*lue 13 python

我编写了一个"基于链"的Python API(类似于jQuery).所以我可以写:

myObject.doStuff().doMoreStuf().goRed().goBlue().die()
Run Code Online (Sandbox Code Playgroud)

问题是我没有找到一种方法来保持长链的语法清洁.在JavaScript中我可以做到

myOjbect
   .doStuf()
   .doMoreStuf()
   .goRed()
   .goBlue()
   .die()
Run Code Online (Sandbox Code Playgroud)

但Python有缩进限制......

Tad*_*eck 22

符合PEP8标准的解决方案:格式化线条

实际上PEP8说:

通过将表达式包装在括号中,可以在多行中分割长行.这些应该优先使用反斜杠来继续行.确保适当缩进续行.

所以我想你的代码应该是这样的:

(
    myOjbect
    .doStuf()
    .doMoreStuf()
    .goRed()
    .goBlue()
    .die()
)
Run Code Online (Sandbox Code Playgroud)

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

从语法来看,每种方法调用返回的值有两种可能的选择:

  1. 每个方法(可能除了die(),不需要,因为它的结果没有被使用)返回修改后的实例(调用它的同一个实例).
  2. 每个方法(仍然die()不需要这样做)返回调用它的实例的副本.

可变对象的解决方案(方法返回原始实例)

第一种情况下(返回相同实例时),将较长行拆分为多个语句的解决方案是:

myObject.doStuf()
myObject.doMoreStuf()
myObject.goRed()
myObject.goBlue()
myObject.die()
Run Code Online (Sandbox Code Playgroud)

真实世界的例子涉及可变对象:

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']
Run Code Online (Sandbox Code Playgroud)

(虽然list.append()不返回任何内容,只是为了保持一致性并明确声明它是可变的)

不可变对象的解决方案(方法返回修改后的副本)

第二种情况下(返回副本时),做类似事情的解决方案是:

myObject = myObject.doStuf()
myObject = myObject.doMoreStuf()
myObject = myObject.goRed()
myObject = myObject.goBlue()
myObject.die()
Run Code Online (Sandbox Code Playgroud)

真实世界的例子涉及不可变对象:

name = '-Tadek-'
name = name.strip('-')  # name == 'Tadek'
name = name.lower()  # name == 'tadek'
name = name.replace('k', 'ck')  # name == 'tadeck'
Run Code Online (Sandbox Code Playgroud)

  • 不能不同意PEP,但我不喜欢那种风格. (2认同)

Joe*_*Joe 8

myOjbect \
   .doStuf() \
   .doMoreStuf() \
   .goRed() \
   .goBlue() \
   .die()
Run Code Online (Sandbox Code Playgroud)

(我感到很抱歉myObject.这听起来很痛苦.)


Lau*_*low 5

虽然我不会称它为“干净”,但可以在括号内打断:

myOjbect.doStuf(
   ).doMoreStuf(arg1, arg2
   ).goRed(
   ).goBlue(
   ).die()
Run Code Online (Sandbox Code Playgroud)

口味各不相同,所以我把它放在一个完整的答案中。