Python 3 map 返回 NoneType 对象列表而不是我修改的类型?

标签 python python-3.x list

我正在努力更好地掌握 Python 3 基础知识,特别是对象并在列表的上下文中修改它们(目前)。

我创建了一个名为 MyThing() 的简单类,它只有一个数字、字母和用于递增数字的实例方法。我对这个程序的目标是创建一个包含 3 个“MyThings”的列表,并以各种方式操作该列表。首先,我遍历列表 (obj_list_1) 并使用每个对象的实例方法递增每个数字。很简单。

我想知道如何做的是使用 map 函数和 lambda 表达式 (obj_list_2) 在一行中执行相同的操作。

#!/usr/bin/env py
import copy

class MyThing:
    def __init__(self, letter='A', number=0):
        self.number = number
        self.letter = letter

    def __repr__(self) -> str:
        return("(letter={}, number={})".format(self.letter, self.number))
        
    def incr_number(self, incr=0):
        self.number += incr

# Test program to try different ways of manipulating lists
def main():
    obj1 = MyThing('A', 1)
    obj2 = MyThing('B', 2)
    obj3 = MyThing('C', 3)

    obj_list_1 = [obj1, obj2, obj3]
    obj_list_2 = copy.deepcopy(obj_list_1)    

    # Show the original list
    print("Original List: {}".format(obj_list_1))
    # output: [(letter=A, number=1), (letter=B, number=2), (letter=C, number=3)]

    # Standard iterating over a list and incrementing each object's number.
    for obj in obj_list_1:
        obj.incr_number(1)
    print("For loop over List, adding one to each number:\n{}".format(obj_list_1))
    # output: [(letter=A, number=2), (letter=B, number=3), (letter=C, number=4)] 

    # Try using map function with lambda
    obj_list_2 = list(map(lambda x: x.incr_number(1), obj_list_2))
    print("Using maps with incr_number instance method:\n{}".format(obj_list_2))
    # actual output: [None, None, None] <--- If I don't re-assign obj_list_2...it shows the proper sequence
    # expected output: [(letter=A, number=2), (letter=B, number=3), (letter=C, number=4)] 

if __name__ == "__main__":
    main()

我想不通的是如何让 map() 返回正确的类型,即“MyThing”的列表。

我知道在 Python 2 和 Python 3 之间,map 更改为返回一个可迭代对象而不是一个列表,所以我确保转换输出。我得到的是“无”对象的列表。

不过,我注意到,如果我不重新分配 obj_list_2,而只是调用 list(map(lambda x: x.incr_number(1), obj_list_2)),然后在下一行打印 obj_list_2,数字如我所料得到更新。

但是,如果我不转换 map iterable 而只是执行 map(lambda x: x.incr_number(1), obj_list_2),则以下打印语句显示列表尚未更新。我在一些文档中读到 map 函数是惰性的,在被某些东西使用之前不会运行......所以这是有道理的。

有没有办法让 list(map(lambda x: x.incr_number(1), obj_list_2)) 的输出真正返回我的对象​​列表?

是否还有其他我没有想到的使用实例方法更新对象列表的很酷的单行解决方案?

最佳答案

TL;DR:只需使用 for 循环。在这种情况下使用 map 没有任何优势。


首先:

  • 您得到一个 None 的列表,因为映射函数返回 None。也就是说,MyThing.incr_number() 不会返回 任何东西,所以 it returns None implicitly .

  • 行数越少不一定越好。两行简单的行通常比一行复杂的行更容易阅读。

  • 请注意,您并不是在 for 循环中创建新列表,您只是在修改现有列表的元素。

  • list(map(lambda)) 比列表推导式更长更难读:

    [x.incr_number(1) for x in obj_list_2]
    

    对比

    list(map(lambda x: x.incr_number(1), obj_list_2))
    

现在,看看Is it Pythonic to use list comprehensions for just side effects?最上面的答案是,它创建了一个永远不会被使用的列表。这就是您的答案:只需使用 for 循环即可。

关于Python 3 map 返回 NoneType 对象列表而不是我修改的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69488024/

相关文章:

python - 使类常量的类型是它所在的类

python - 为第三方库/模块扩展 stub 文件

python - 柜台 list

python - 关于MySQL "SELECT *"的内存问题

python - "Fatal Python error: (pygame parachute) Segmentation Fault"改变窗口时

python - 查找一个类注册的所有抽象基类

python - PyQt 保持纵横比固定

list - 在列表列表中查找形状

c# - Razor @foreach 列表问题

python sklearn GradientBoostingClassifier热启动报错