Python 多映射上的迭代

Python 多映射上的迭代,python,lazy-evaluation,Python,Lazy Evaluation,我有一个关于Python(3)在计算多个映射时如何在内部循环的问题。下面是一个毫无意义的例子: 来自随机导入randint A=[randint(0,20)表示范围(100)] map1=map(λa:a+1,a) map2=map(λa:a-1,map1) B=列表(map2) 因为map()生成一个惰性表达式,所以在调用list(map2)之前,实际上不会计算任何内容,对吗 当它最终进行计算时,它更接近于这些方法中的哪一种 循环方法1: A=[randint(0,20)表示范围内(100)

我有一个关于Python(3)在计算多个映射时如何在内部循环的问题。下面是一个毫无意义的例子:

来自随机导入randint
A=[randint(0,20)表示范围(100)]
map1=map(λa:a+1,a)
map2=map(λa:a-1,map1)
B=列表(map2)
因为
map()
生成一个惰性表达式,所以在调用
list(map2)
之前,实际上不会计算任何内容,对吗

当它最终进行计算时,它更接近于这些方法中的哪一种

循环方法1:

A=[randint(0,20)表示范围内(100)]
temp1=[]
对于a中的a:
temp1.追加(a+1)
B=[]
对于temp1中的t:
B.附加(t-1)
循环方法2:

A=[randint(0,20)表示范围内(100)]
B=[]
对于a中的a:
温度=a+1
B.附加(临时-1)
还是以完全不同的方式计算

通常情况下,
map()
函数会生成一个生成器,而该生成器在明确要求之前不会生成任何输出或计算任何内容。将生成器转换为列表本质上类似于请求它输入下一个元素,直到没有下一个元素为止

我们可以在命令行上进行一些实验,以了解更多信息:

>>> B = [i for i in range(5)]
>>> map2 = map(lambda b:2*b, B)
>>> B[2] = 50
>>> list(map2)
[0, 2, 100, 6, 8]
我们可以看到,即使我们在创建生成器之后修改了
B
,我们的更改仍然反映在生成器的输出中。因此,
map
似乎保留了对原始iterable的引用,从原始iterable创建了它,并且只在请求时一次计算一个值


在您的示例中,这意味着过程如下所示:

A = [2, 4, 6, 8, 10]
b = list(map2)
    b[0] --> next(map2) = (lambda a: a-1)(next(map1))
             --> next(map1) = (lambda a: a+1)(next(A)) 
                 --> next(A) = A[0] = 2
             --> next(map1) = 2+1 = 3
         --> next(map2) = 3-1 = 2
    ...

按照人类的说法,
map2
的下一个值是通过询问
map1
的下一个值来计算的。反过来,这是根据您最初设置的
A
计算得出的。

这可以通过对具有副作用的函数使用
map
进行调查。一般来说,您不应该对真正的代码执行此操作,但可以对行为进行调查

def f1(x):
打印('f1已调用',x)
返回x
def f2(x):
打印('f2在'x'上调用)
返回x
nums=[1,2,3]
map1=map(f1,nums)
map2=map(f2,map1)
对于map2中的x:
打印(“打印”,x)
输出:

f1在1上调用
f2呼叫1
印刷1
f1在2号呼叫
f2在2号呼叫
印刷2
f1在3号呼叫
f2在3号呼叫
印刷3
因此,每个函数在可能被调用的最晚时间被调用<代码>f1(2)在循环使用数字1完成之前不会被调用。在循环需要映射中的第二个值之前,不需要对数字2执行任何操作。

先决条件: