Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using lambda function to change value of an attribute

Tags:

python

lambda

Can I use lambda function to loop over a list of class objects and change value of an attribute (for all objects or for the one that meet a certain condition)?

class Student(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

student1 = Student('StudOne',18)
student2 = Student('StudTwo',20)
student3 = Student('StudThree',29)
students = [student1,student2,student3]

new_list_of_students = map(lambda student:student.age+=3,students)
like image 502
python dev Avatar asked Aug 02 '14 13:08

python dev


People also ask

Can a lambda function return a value?

The lambda function above is defined and then immediately called with two arguments ( 2 and 3 ). It returns the value 5 , which is the sum of the arguments.

Can lambda function be assigned to a variable?

Creating a Lambda Function The lambda operator cannot have any statements and it returns a function object that we can assign to any variable.

Can lambda return 2 values?

It's one return with one value (which happens to be a tuple).


2 Answers

Unfortunately, that’s not possible since the body of a lambda only allows for simple expressions while a student.age += 3 is a statement. So you can’t use a lambda there. You could however still use the map solution:

def incrementAge (student):
    student.age += 3
    return student

students2 = map(incrementAge, students)

Note that students2 will contain the same students as students though, so you don’t really need to capture the output (or return something from incrementAge). Also note that in Python 3, map returns a generator which you need to iterate on first. You can call list() on it to do that: list(map(…)).

Finally, a better solution for this would be to use a simple loop. That way, you don’t have overhead of needing a function or create a duplicate students list, and you would also make the intention very clear:

for student in students:
    student.age += 3
like image 111
poke Avatar answered Nov 15 '22 08:11

poke


Using a simple for-loop to retrieve the students to update the age for each is good enough like others said, but if you still want to use a lambda to update the values, you may need to leverage the exec() function:

_ = list(map(lambda student: exec("student.age+=3"), students))
for _ in students: print(_.age)

Output:

21 23 32

In this case, what actually does the updating is the exec(), and the map() just yields None. So the returned result makes no sense and I put a _ to clarify this. A more concise form would be this:

list(map(lambda _: exec("_.age+=3"), students))

Besides, if only considering what you want to do, you don't need to use a map() at all (probably more confusing though):

[(lambda _: exec("_.age += 3"))(_) for _ in students]

Furthermore, a lambda can be discarded either:

[exec("_.age += 3") for _ in students]

As you can see, no "trick" codes above seem more concise than what other answers post:

for s in students:
    s.age += 3

So maybe the so-called "one-liner" is useful just when it comes to having fun... :)

like image 45
YFlag Avatar answered Nov 15 '22 06:11

YFlag