1

I want to make a model of "walking" over a gird.

enter image description here

so I created 8 functions:

g0 = lambda ct: ct.append((lambda (x,y): (x-1,y))(ct[-1]))
g1 = lambda ct: ct.append((lambda (x,y): (x-1,y+1))(ct[-1]))
g2 = lambda ct: ct.append((lambda (x,y): (x,y+1))(ct[-1]))
g3 = lambda ct: ct.append((lambda (x,y): (x+1,y+1))(ct[-1]))
g4 = lambda ct: ct.append((lambda (x,y): (x+1,y))(ct[-1]))
g5 = lambda ct: ct.append((lambda (x,y): (x+1,y-1))(ct[-1]))
g6 = lambda ct: ct.append((lambda (x,y): (x,y-1))(ct[-1]))
g7 = lambda ct: ct.append((lambda (x,y): (x-1,y-1))(ct[-1]))

but when I try to apply any function I get None:

print g0([(50,50)])
None

well, Iet's try more traditional way:

def g0(ct):
    ct.append((lambda (x,y): (x-1,y))(ct[-1]))
    return ct

that's works as expected:

[(50, 50), (49, 50)]

But when I try

def g0(ct):          
    return ct.append((lambda (x,y): (x-1,y))(ct[-1]))

the result is also None, Why?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Sergey Sosnin
  • 1,313
  • 13
  • 30
  • 4
    `list.append()` always returns `None`, because the list is altered in-place instead. *Should* the list be altered in-place or do you want a new list object returned, leaving `ct` unaltered? – Martijn Pieters May 13 '14 at 14:35

3 Answers3

7

Your lambda function appends an element to a list and it returns nothing (None):

g0 = lambda ct: ct.append((lambda (x,y): (x-1,y))(ct[-1]))

More precisely, it returns nothing because ct.append(...) is a method that returns None and your lambda returns what ct.append(...) returns.

In your second example, you are actually returning the list, so it works as you expect:

def g0(ct):
   ct.append((lambda (x,y): (x-1,y))(ct[-1]))
   return ct

However, be careful because even if you don't return the list, your list is actually altered.

You are also asking if it's possible to rewrite the lambda function to return the list... Well, yes but do not mention my name if someone asks you anything about this:

>>> g0 = lambda ct: (ct.append((lambda (x,y): (x-1,y))(ct[-1])) or ct)
>>> print g0([(50,50)])
[(50, 50), (49, 50)]

The code is not easy to read and I would suggest you to use functions instead.

Also, this question is related to your question: why the list.append return None?

Community
  • 1
  • 1
Maxime Chéramy
  • 17,761
  • 8
  • 54
  • 75
7

list.append() alters the list in-place, and like all Python standard library methods that operate directly on the underlying mutable object, the method returns None to signal this.

Your lambda returns not the list object, but the result of ct.append(); e.g. None. You have two options:

  • don't alter the original list, but return a new list instead:

    g0 = lambda ct: ct + [(lambda (x,y): (x-1,y))(ct[-1])]
    
  • append to the original list and chain the original list object with or to return it instead of None:

    g0 = lambda ct: ct.append((lambda (x,y): (x-1,y))(ct[-1])) or ct
    

Demo:

>>> ct = [(50,50)]
>>> g0 = lambda ct: ct + [(lambda (x,y): (x-1,y))(ct[-1])]
>>> g0(ct)
[(50, 50), (49, 50)]
>>> ct
[(50, 50)]
>>> g0 = lambda ct: ct.append((lambda (x,y): (x-1,y))(ct[-1])) or ct
>>> g0(ct)
[(50, 50), (49, 50)]
>>> ct
[(50, 50), (49, 50)]

The first version leaves the original list unaffected; a new list object is returned. The second approach altered the original list; the return value and ct both refer to the same object.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

When you append an element to a list you return None as default, this leads to your expressions returning None.

In your 2nd example you append a lambda function to your list and then return the list. Which is why it works as you expect it should.

Ffisegydd
  • 51,807
  • 15
  • 147
  • 125