2012-01-06 5 views
1

Что было бы красивым способом отступать/форматировать строку в функции ниже? Или я не пытаюсь написать это как один лайнер?Форматирование длинных строк python

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    return reduce(lambda (ax,ay,aw,ah), (bx,by,bw,bh): (min(ax,bx), 
                 min(ay,by), 
                 max(ax+aw, bx+bw), 
                 max(ay+ah, by+bh)), rects) 

или, может быть,

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    return reduce(lambda (ax,ay,aw,ah), 
         (bx,by,bw,bh): (min(ax,bx), min(ay,by), 
             max(ax+aw, bx+bw), max(ay+ah, by+bh)), 
        rects) 

Я обычно просто своего рода «получить творческий» в таких ситуациях, и я знаю, что, вероятно, нет «правильный» путь, я просто интересно ваше мнение и привычки.

+0

-1 Ваша функция лямбды неправильно (см моего ответа) ... это перевешивает любые опасения по поводу длины линии и т.д. –

+0

Простите? Мой вопрос был не в том, выполняет ли функция то, что она говорит, хотя вы правы, что это «неправильно». Мой вопрос был о том, как отформатировать это красиво. – noio

+0

Вы просили мнения. У тебя есть. Исправьте структуру данных, если сможете. Напишите правильную функцию редуктора. Тогда волнуйтесь о длине линии. –

ответ

2

Если вы беспокоитесь о длинных очередях, не используйте lambda. Вместо этого используйте обычную именованную функцию.

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    def bounding_rect_reducer((ax, ay, aw, ah), (bx, by, bw, bh)): 
     return (min(ax,bx), 
       min(ay,by), 
       max(ax+aw, bx+bw), 
       max(ay+ah, by+bh)) 

    return reduce(bounding_rect_reducer, rects) 
2

Я думаю, что это зависит от программиста и от ситуации, но я обычно не люблю выделять переменную, чтобы иметь более короткие строки.

Глядя на ваши 2 примера, я хотел бы пойти на второй, или это один:

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    return reduce(
     lambda (ax,ay,aw,ah), (bx,by,bw,bh): 
     (min(ax,bx), min(ay,by), max(ax+aw, bx+bw), max(ay+ah, by+bh) 
    ), 
     rects 
    ) 
+2

Есть ли причина не выделять переменную? Я нахожу, что для длинных строк присвоение хорошего имени некоторому результату делает код намного более очевидным. Плюс функции местных жителей довольно дешевы. –

+0

Нет причин вообще. Это личный выбор, так же, как разделение длинных строк. Обычно я предпочитаю иметь хорошее имя функции, которое должно описывать, что он делает (в названии или над комментариями). – dresende

0

Я хотел бы предложить следующее:

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    return reduce(lambda (X,Y,W,H), (x,y,w,h): (min(X,x), min(Y,y), 
               max(X+W, x+w), 
               max(Y+H, y+h)), rects) 

Снижение каждый аргумент к одному символу действительно экономит место, что помогает этому выглядеть чище. Другим вариантом было бы определить лямбда-функцию на отдельной строке (возможно, даже с def), чтобы аргументы были не так уж далеки.

+0

-1 В вашем коде отображается горизонтальная полоса прокрутки SO. –

+0

@JohnMachin - Хорошая точка, добавила дополнительную линию, чтобы сократить ее. –

+0

Это все еще fugly: отступы не имеют ничего общего с синтаксической структурой; он, по-видимому, основан исключительно на том, что линии не слишком длинны. –

4

Прежде всего, избегайте длинных линий, если это возможно. Этот конкретный пример может быть написан гораздо более читаемо, как

def rects_bound(rects): 
    x0 = min(x for x, y, w, h in rects) 
    y0 = min(y for x, y, w, h in rects) 
    x1 = max(x + w for x, y, w, h in rects) 
    y1 = max(y + h for x, y, w, h in rects) 
    return x0, y0, x1, y1 

Если вы предпочитаете, чтобы избежать переменных, вы можете также использовать

def rects_bound(rects): 
    return (min(x for x, y, w, h in rects), 
      min(y for x, y, w, h in rects), 
      max(x + w for x, y, w, h in rects), 
      max(y + h for x, y, w, h in rects)) 

, который я до сих пор находят гораздо более удобным для чтения, чем ваш исходный код.

(Обратите внимание, что я предполагаю, что rects допускает несколько итераций.)

+1

Это более читаемо, да, но четыре итерации? – noio

+0

@Noio: В чем проблема с четырьмя итерациями? (Для чего это стоит, моя версия в два раза быстрее, чем ваша на моей машине.) –

+0

@SvenMarnach Одна из проблем заключается в том, что в вашей версии нельзя больше передавать генератор в качестве аргумента 'rects'. – Bolo

1

Ваша функция лямбда неправильна. Чтобы исправить это, он сделает его еще длиннее и потребует избыточных вычислений. Используйте вместо Защиты:

def rects_bound(rects): 
    """ Returns a rectangle that bounds all given rectangles 
    """ 
    def bound_2_rects((ax, ay, aw, ah), (bx, by, bw, bh)): 
     x = min(ax, bx) 
     y = min(ay, by) 
     return x, y, max(ax+aw, bx+bw) - x, max(ay+ah, by+bh) - y 

    return reduce(bound_2_rects, rects)