2

I want to create a lambda function that takes two numpy arrays and sets a slice of the first to the second and returns the newly set numpy array.

Considering you can't assign things in lambda functions is there a way to do something similar to this?

The context of this is that I want to set the centre of a zeros array to another array in a single line, and the only solution I could come up with is to use reduce and lambda functions.

I.e. I'm thinking about the condensation of this (where b is given):

a = numpy.zeros( numpy.array(b.shape) + 2)
a[1:-1,1:-1] = b

Into a single line. Is this possible? This is just an exercise in oneliners. I have the code doing what I want it to do, I'm just wondering about this for the fun of it :).

2
  • Replace a[1:-1,1:-1] by a[[slice(1,-1)]*a.ndim] to support a.ndim != 2. numpy.put, numpy.place and the like allow to change an array inplace. Commented Dec 9, 2009 at 23:16
  • This sounds complex enough that you probably shouldn't use a lambda for it if you care about being 'pythonic'. The reason lambdas are limited to a single line is precisely because it's easy to get carried away with them. There's no other technical reason. Commented Dec 10, 2009 at 1:26

1 Answer 1

4

This is ugly; you should not use it. But it is oneline lambda as you've asked:

f = lambda b, a=None, s=slice(1,-1): f(b, numpy.zeros(numpy.array(b.shape) + 2))\
                      if a is None else (a.__setitem__([s]*a.ndim, b), a)[1]

What is __setitem__?

obj.__setitem__(index, value) is equivalent to obj[index] = value in this case. Example:

class A:
    def __setitem__(self, index, value):
       print 'index=%s, value=%s' % (index, value)

a = A()
a[1, 2] = 3

It prints:

index=(1, 2), value=3

Why does __setitem__() return None?

There is a general convention in Python that methods such as list.extend(), list.append() that modify an object in-place should return None. There are exceptions e.g., list.pop().

Y Combinator in Python

Here's blog post On writing Python one-liners which shows how write nameless recursive functions using lambdas (the link is suggested by @Peter Hansen).

Sign up to request clarification or add additional context in comments.

4 Comments

hmmm this is definitely leaning towards what I want. Could you give me any information on this "setitem" method? I can't seem to find it in the docs. And as far as I can tell "numpy.put" flattens out the array, according to the docs. Thanks!
In my mind this: print numpy.zeros( (10,10) ).__setitem__( numpy.s_[1:-1,1:-1] , numpy.arange(64).reshape(8,8) ) should print out a 10x10 array with the centre 8x8 being arange(64). however it just prints out "none". This is probably horribly unreadable, haha. Where's the error? Python doesn't mind doing all these steps if I they are in multiple steps. So it's probably my fault somewhere along the line.
You might want to add this link to the response: blog.sigfpe.com/2008/09/on-writing-python-one-liners.html
@VolatileStorm: I've added info about __setitem__.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.