使用lambda函数更改属性的值

时间:2014-08-02 13:57:18

标签: python lambda

我是否可以使用lambda函数循环遍历类对象列表并更改属性的值(对于所有对象或满足特定条件的对象)?

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)

5 个答案:

答案 0 :(得分:3)

不幸的是,这是不可能的,因为body of a lambda只允许simple expressionsstudent.age += 3statement。所以你不能在那里使用lambda。但是,你仍然可以使用地图解决方案:

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

students2 = map(incrementAge, students)

请注意,students2将包含与students相同的学生,因此您不需要捕获输出(或从incrementAge返回内容)。另请注意,在Python 3中,map返回一个您需要首先迭代的生成器。您可以在其上调用list()来执行此操作:list(map(…))

最后,更好的解决方案是使用简单的循环。这样,您就没有需要功能或创建重复学生列表的开销,您也可以非常明确地表达意图:

for student in students:
    student.age += 3

答案 1 :(得分:2)

使用简单的for循环来检索6来更新每个students就像其他人所说的一样好,但是如果您仍然想使用age来更新{值,则可能需要利用lambda函数:

exec()

输出:

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

在这种情况下,实际上进行的更新是21 23 32 ,而exec()仅产生map()。因此,返回的结果没有任何意义,因此我添加了None来阐明这一点。更为简洁的形式是:

_

此外,如果仅考虑要执行的操作,则根本不需要使用list(map(lambda _: exec("_.age+=3"), students)) (不过可能会更令人困惑):

map()

此外,[(lambda _: exec("_.age += 3"))(_) for _ in students] 可以被丢弃:

lambda

如您所见,上面没有“技巧”代码似乎比其他答案更简洁:

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

所以也许所谓的“单线”在获得乐趣时很有用... :)

答案 2 :(得分:1)

Lambda函数只能包含表达式,而不能包含语句。 Python中的赋值是一种陈述。 Lambdas无法完成任务。此外,赋值语句不会计算其值,因此您的地图不会生成学生列表。

你想要这个:

for student in students:
    student.age += 3

这不会给你一个新列表,它会修改旧列表,但无论如何你的旧列表都会被修改,你没有做任何事来产生新学生。

答案 3 :(得分:1)

您可以使用setattr,这会将更改应用于对象。一个很大的好处是你可以继续使用相同的列表。

map(lambda s: setattr(s, 'age', s.age + 3), students)

来自文档:

  

The function assigns the value to the attribute, provided the object allows it. For example, setattr(x, 'foobar', 123) is equivalent to x.foobar = 123.

等效于:

for s in students:
    s.age += 3

如果确实想要一个新列表:

上述方法不会返回新列表;而是返回Nonesetattr的返回值)。添加or与数组中所需对象的比较(在本例中为s)将会对此进行修改。

new_students = map(lambda s: setattr(s, 'age', s.age + 3) or s, students)

比较相当于None or s,它总是会产生后者。另请注意,新列表与旧列表相同。

答案 4 :(得分:0)

问:“我可以使用lambda函数循环遍历类对象列表并更改属性值”

答:是的......但你不应该。它的编码风格很差,效率低下,而且只适用于代码高尔夫等

你应该像其他两个答案一样写出来。

......但如果你真的想......

new_list_of_students = [(lambda student:(setattr(student, 'age', student.age+3), 
student))(s)[1] for s in students]

print [student.age for student in new_list_of_students]

打印:

[21, 23, 32]

......甚至:

from operator import itemgetter
new_list_of_students = map(itemgetter(1),map(lambda student:(setattr(student, 
'age', student.age+3), student),students))

print [student.age for student in new_list_of_students]

[输出相同]