在Python中把布尔值列表转为整数。

问题描述 投票:0回答:1

我在使用lambdas语法时遇到了问题,我试图将一个booleans列表翻译成一个整数值,但我得到了一个错误,我不明白为什么。

下面是代码。

from functools import reduce

binary = [True, True, False, True]

L = list(range(len(binary)))      #Step 1
print(L)                          #[0, 1, 2, 3]
L = map(lambda a: 2**a, L)        #Step 2
print(L)                          #[1, 2, 4, 8]
L = zip(binary, L)                #Step 3
print(L)                          #[(True, 1),(True, 2),(False, 4),(True, 8)]
L = filter(lambda a, b: a, L)     #Step 4
print(L)                          #[(True, 1),(True, 2),(True, 8)] not sure
L = map(lambda a, b: b, L)        #Step 5
print(L)                          #?????
L = reduce(lambda a, b: a + b, L) #Final step 
print(L)                          #11

输出:

Traceback (most recent call last):
  File "C:/Users/axel_/PycharmProjects/Python_Subject_Exam/19_new_exam_binary_list_translation.py", line 27, in <module>
    L = reduce(lambda a, b: a + b, L)
TypeError: <lambda>() missing 1 required positional argument: 'b'
[0, 1, 2, 3]
<map object at 0x00000267FAFE5388>
<zip object at 0x00000267FAFE50C8>
<filter object at 0x00000267FAFE5248>
<map object at 0x00000267FAFE4EC8>

Process finished with exit code 1

谁能帮我调试一下?

python lambda filter boolean reduce
1个回答
2
投票

我想这可以解决你的问题。我将在代码中写一些注释来帮助你理解。

from functools import reduce

binary = [True, True, False, True]
L = list(range(len(binary)))       #[0, 1, 2, 3]

L = map(lambda a: 2**a, L)         #[1, 2, 4, 8]

L = zip(binary, L)                 #[(True, 1), (True, 2), (False, 4), (True, 8)]

L = filter(lambda x: x[0], L)      #<--- an item from zip() is an ((unpacked)) tuple

L = map(lambda x: x[1], L)
L = reduce(lambda a, b: a + b, L)
print(L)                           #11

1
投票

如果你是新手,这是对迭代器的挑战之一。

迭代器是在每个项目被拉下迭代器时被评估的,这意味着当你调用reduce来组合结果时,所有的lambda表达式都在那个时候被评估。你的例子这相当于下面的表达式。

L = list(range(len(binary)))
L = reduce(lambda a, b: a + b, 
    map(lambda a, b: b, 
        filter(lambda a, b: a, 
            zip(binary, 
                map(lambda a: 2**a, L)
            )
        )
    )
)
print(L)  

令人困惑吗?

在你的例子中,这一行 L = filter(lambda a, b: a, L) #Step 4 有一个错误。过滤器表达式将一个可调用的表达式,该表达式将一个 单一 参数以及一个可迭代参数,但由于它没有被评估到最后,你会得到一个混乱的错误。

一种方法(也是调试时的好方法)是将每一步都包在一个调用列表中,以迫使评估发生在每一行,例如 L = list(filter(lambda a, b: a, L)). 这将使错误的位置更加明显。

或者使用生成器表达式而不是 filtermap eg:

# filter (return odd numbers between 1 and 10)
result_a = filter(lambda a: a % 2, range(1, 11))
result b = (a for a in range(1, 11) if a % 2)

# map (return powers of 2)
result_a = map(lambda a: 2**a, range(11))
result_b = (2**a for a in range(11))

所有的结果都是一样的 但生成器表达式有另一个技巧 你可以使用元组解包,这样就可以了。

result = (b for a, b in zip(binary, range(len(binary))) if a)

此外,python还有其他的内置功能,可以进一步简化代码。

Enumerate 将返回一个计数器,加上迭代器中的每个元素,使得前三步可以简化为。

# 1 step 1, 2 and 3 can be simplified with enumerate
L = ((i**2, b) for i, b in enumerate(L))

接下来可以用sum代替reduce,sum将迭代表中的所有数值加在一起。

L = reduce(lambda a, b: a + b, L)
# is equivalent to
L = sum(L)

然后把所有的数值加在一起 整个序列就可以简化为:

L = sum(2**i for i, b in enumerate(binary) if b)

希望能帮到你

© www.soinside.com 2019 - 2024. All rights reserved.