Подтвердить что ты не робот

Укладка длинных цепочек в Python

Я написал API-интерфейс Python, основанный на цепочке (аналогично jQuery). Поэтому я могу написать:

myObject.doStuff().doMoreStuf().goRed().goBlue().die()

Проблема в том, что я не нашел способа сохранить синтаксис чистым с длинными цепочками. В JavaScript я мог просто сделать

myOjbect
   .doStuf()
   .doMoreStuf()
   .goRed()
   .goBlue()
   .die()

но у Python есть ограничения отступов...

4b9b3361

Ответ 1

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'

Ответ 2

myOjbect \
   .doStuf() \
   .doMoreStuf() \
   .goRed() \
   .goBlue() \
   .die()

(Мне жаль myObject. Это звучит довольно болезненно.)

Ответ 3

Хотя я бы не назвал его "чистым", можно заключить в круглую скобку:

myOjbect.doStuf(
   ).doMoreStuf(arg1, arg2
   ).goRed(
   ).goBlue(
   ).die()

Вкусы меняются, поэтому я даю им ответ на полноту.

Ответ 4

Я обнаружил, что хороший способ сделать "цепочки" красивым - просто набрать немного больше:

obj = myObject.doStuff()
obj = obj.doMoreStuf()
obj = obj.goRed()
obj = obj.goBlue()
obj = obj.die()

Или лучше: используйте значащие имена, делая код более очевидным.

obj = myObject.doStuff().doMoreStuf()
colored_object = obj.goRed().goBlue()
colored_object.die()

Ответ 5

Я не думаю, что прикованные методы, подобные этому, очень часто используются в python (если вообще). Один из вариантов - использовать API, который выглядит как

myObject.do(
    'Stuff',
    'MoreStuff',
    'Red',
    'Blue',
    'die',
    )

хотя вы можете получить более улокальный совет, если вы дадите нам реальный пример - трудно догадаться, какие операции здесь представлены. Возможно, некоторые из них должны быть объединены или помещены в __init__ (например, цвет может быть установлен путем передачи необязательного аргумента в __init__).