Python,应用于对象属性列表的映射函数

Python, map function applied to list of objects' attributes

出于任何实际原因,我有兴趣将 map 函数应用于对象列表,更具体地说,触发其中的方法。

考虑这个例子class:

class Something:

  def __init__(self):
    self.attr = 0

  def step(self):
    self.attr += 1

现在,使用 for 循环,我可以为列表中的每个对象迭代执行 step 方法并查看结果。

obj_list1 = [Something() for i in range(10)]
for elem in obj_list1:
  elem.step()

[elem.attr for elem in obj_list1]  
>>>
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

但是,如果我尝试使用 lambda 函数进行映射,事情就会出错:

obj_list2 = [Something() for i in range(10)]
list(map(lambda x: x.step(), obj_list2))
>>> 
[None, None, None, None, None, None, None, None, None, None]

请注意,在最后一个代码片段中,我期待的是 Something 对象的列表,而不是 attr 属性。但是,None 在每个实例中都被 return 编辑了。

我的问题是:(A) 为什么要为每个元素编辑 None return?以及 (B) 应该如何以矢量化方式对一系列对象进行操作?

编辑:如回答所述,我在 step 方法中没有 return 值。可能有几种方法可以解决这个问题,其中一种方法本身不会改变 class,如下所示:

def trigger(obj):
  obj.step()
  return obj.attr

obj_list3 = [Something() for i in range(10)]
list(map(trigger, obj_list3))  
>>>
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

None然而,map 是一种完全奇怪的以矢量化方式处理对象的方式吗?有更好的选择吗?等等

Edit2:在我最初的问题中,引用 obj_list2,而 None 值的列表是 returned,当我调查列表中的属性时,所有这些都是增加到 1。有趣的发现!

您的函数步骤没有 return 值

def step(self):
     self.attr += 1

所以将其映射到任何东西 returns 一个包含 None

的列表

在您的另一个示例中,您 return 编辑了 elem.attr,这就是您得到不同结果的原因。

第二题,在

之后
obj_list3 = [Something() for i in range(10)]
list(map(trigger, obj_list3)) 

打印出 obj_list3 以查看每个对象是否已被映射尝试更改。

正在调用映射 step,但您的步骤函数没有 return 语句,因此使用 None 的默认 return。

如果您希望地图以您所说的 Something 对象列表结尾,您可以 return self 从以下步骤开始:

def step(self):
    self.attr += 1
    return self # or perhaps return self.attr

尽管在这里使用 map 不一定是正确的,因为 map 的想法是将一个值的事物转换为另一个值,而您的 step 是在内部就地更改对象。

我认为 for 循环方式很好:

for elem in obj_list1:
  elem.step()