省略列表理解中的元素

Omit elements in list comprehension

有以下简单的脚本:

def MyFunction(digit):
    if digit < 4:
        return digit
    else:
        return None

A = [1, 2, 3, 4, 5]
B = [MyFunction(x) for x in A]
print(B) # [1, 2, 3, None, None]

问题:

是否可以通过某种方式重写 MyFunction(),使 B 等于 [1, 2, 3] 而无需 None?请不要建议我在列表推导中使用 if 表达式,在列表推导之后处理 B

要过滤元素,您需要使用 filter() 或使用 if 的列表理解。

即:

B = filter(lambda digit: digit < 4, A)

您可以使用您的函数,但它应该 return boolean:

def MyFunction(digit):
    if digit < 4:
        return True
    else:
        return False
B = filter(MyFunction, A)

或者简单地说:

def MyFunction(digit):
    return digit < 4

有列表理解:

B = [digit for digit in A if digit < 4]

Is it possible to rewrite MyFunction() somehow, so B becomes equal to [1, 2, 3] without None? Please, don't recommend me to use if expressions in the list comprehension, process B after list comprehension etc

不,不是。您的列表理解不会改变列表的长度。在 MyFunction() 中您无能为力。您 必须 在列表理解中使用 if 或对列表进行某种预处理或 post 处理。

the Python language reference所述:

The comprehension consists of a single expression followed by at least one for clause and zero or more for or if clauses. In this case, the elements of the new container are those that would be produced by considering each of the for or if clauses a block, nesting from left to right, and evaluating the expression to produce an element each time the innermost block is reached.

for 次迭代获得一个元素。这是内置在语言中的。

从函数中调整迭代器是可能的,但非常丑陋。不幸的是,我无法摆脱最后一个 None,但也许其他人可以接受这个想法并对其进行完善。这是我的努力,我扩展了测试数据:

import sys

def MyFunction(digit):
    if digit < 4:
        return digit
    else:
        while digit >= 4:
            try:
                digit = sys._getframe(1).f_locals['.0'].__next__()
            except StopIteration:
                break
        else:
            return digit

A = [6, 7, 1, 2, 3, 4, 5]
B = [MyFunction(x) for x in A]
print(B)

产生:

[1, 2, 3, None]

我完全希望有人会说这种做法非常危险并且特定于实现 - 我不会反对这样的评论。