tags:

views:

172

answers:

2

To help me better understand lambda I wrote this short snippet that rotates and transforms a quad (I hope I got the math right). Now, I want to replace the three steps below with one liner lambdas, possibly in conjunction with map().

Im using a vector class but hopefully, the functions are clear as to what they do.

self.orientation = vector(1,0)
self.orientation.rotate(90.0)

#the four corners of a quad
points = (vector(-1,-1),vector(1,-1),vector(1,1),vector(-1,1))
print points

#apply rotation to points according to orientation
rot_points = []
for i in points:
    rot_points.append(i.rotated(self.orientation.get_angle()))
print rot_points

#transform the point according to world position and scale
real_points = []
for i in rot_points:
    real_points.append(self.pos+i*self.scale)
print real_points

return real_points
+8  A: 

You could use map, reduce, et al, but nowadays list comprehensions are the preferred way to do things in Python:

rot_points  = (i.rotated(self.orientation.get_angle()) for i in points)
real_points = [self.pos+i*self.scale for i in rot_points]

Notice how I used (parentheses) instead of [brackets] in the first line. That is called a generator expression. It allows rot_points to be constructed on the fly as the points are used in the second line rather than constructing all of the rot_points in memory first and then iterating through them. It could save some unnecessary memory usage, basically, if that's a concern.

John Kugelman
So much good python in one post!
David Berger
so, strictly speaking, generators are preferred, not list comprehensions :)
zweiterlinde
zweiterlinde: So its generator expressions > list comprehensions > lambdas ?
mizipzor
Broadly speaking, yes. If you have very small lists then a generator may be too much overhead: e.g. `range(5)` but `xrange(10000)`.
John Kugelman
A: 

Note that you're unnecessarily calling get_angle() for each point, when really it's constant over the life of the loop.

I'd try this:

angle = self.orientation.get_angle()
real_points = [self.pos+point.rotated(angle)*self.scale for point in points]

I don't think it's a bad idea to create a helper function in this case either, since you're doing quite a bit to each point. A new function is more readable:

angle = self.orientation.get_angle()

def adjust_point(point):
     point = point.rotated(angle)
     point *= self.scale
     point += self.pos
     return point

real_points = [adjust_point(p) for p in point]
Triptych
I honestly think your first code snippet is more readable. :P
mizipzor