noio
noio

Reputation: 5812

Formatting long python lines

What would be a pretty way to indent/format the line in the function below? Or should I not be trying to write this as a one liner at all?

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)

or maybe

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)

I usually just kind of "get creative" in these situations, and I know there is probably no "right" way, I'm just interested in your opinions and habits.

Upvotes: 1

Views: 476

Answers (5)

John Machin
John Machin

Reputation: 82924

Your lambda function is wrong. To fix it would make it even longer and involve redundant computation. Use a def instead:

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)

Upvotes: 1

Andrew Clark
Andrew Clark

Reputation: 208425

I would suggest the following:

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)

Reducing each argument to a single character really saves on space which helps this look cleaner. Another option would be to define the lambda function on a separate line (possibly even with def) so that the arguments aren't that far over in the first place.

Upvotes: 0

ᅠᅠᅠ
ᅠᅠᅠ

Reputation: 66940

If you're worried about long lines, don't use a lambda. Use a regular named function instead.

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)

Upvotes: 2

Sven Marnach
Sven Marnach

Reputation: 601489

First of all, avoid long lines if possible. This particular example could be written much more readably as

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

If you prefer to avoid the variables, you could also use

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))

which I still find much more readable than your original code.

(Note that I assume rects allows multiple iterations.)

Upvotes: 4

dresende
dresende

Reputation: 2230

I think this depends on the programmer and on the situation but I usually don't like to allocate a variable just to have shorter lines.

Looking at your 2 examples, I would go for the second one, or this one:

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
    )

Upvotes: 2

Related Questions