在python中将带有两个参数的函数传递给filter()

Hom*_*map 8 python list python-2.7

鉴于以下列表:

DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT']
Run Code Online (Sandbox Code Playgroud)

我想过滤超过3个字符的字符串.我用以下代码实现了这一点:

使用for循环:

long_dna = []
for element in DNA_list:
    length = len(element)
    if int(length) > 3:
        long_dna.append(element)
print long_dna
Run Code Online (Sandbox Code Playgroud)

但我希望我的代码更通用,所以我以后可以过滤任何长度的字符串,所以我使用一个函数和for循环:

def get_long(dna_seq, threshold):
    return len(dna_seq) > threshold

long_dna_loop2 = []
for element in DNA_list:
    if get_long(element, 3) is True:
        long_dna_loop2.append(element)
print long_dna_loop2
Run Code Online (Sandbox Code Playgroud)

我希望使用相同的通用性,filter()但我无法实现这一点.如果我使用上面的函数get_long(),当我使用它时,我根本无法传递参数filter().这是不可能的还是有办法绕过它?

我的代码与filter()特定情况:

def is_long(dna):
        return len(dna) > 3

    long_dna_filter = filter(is_long, DNA_list)
Run Code Online (Sandbox Code Playgroud)

And*_*ini 15

使用lambda提供的门槛,就像这样:

filter(lambda seq: get_long(seq, 3),
       dna_list)
Run Code Online (Sandbox Code Playgroud)


Lea*_*rtS 15

你要做的是被称为部分函数应用程序:你有一个带有多个参数的函数(在这种情况下,2)并且希望得到一个从它派生的函数,其中一个或多个参数是固定的,然后你可以传递给它filter.

某些语言(特别是功能语言)具有"内置"功能.在python中,您可以使用lambdas来执行此操作(正如其他人所示)或您可以使用该functools.特别是functools.partial:

partial()用于部分函数应用程序,它"冻结"函数的参数和/或关键字的某些部分,从而产生具有简化签名的新对象.例如,partial()可用于创建一个callable,其行为类似于int()函数,其中base参数默认为2:

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

filter(functools.partial(get_long, treshold=13), DNA_list)
Run Code Online (Sandbox Code Playgroud)


mha*_*wke 10

你需要用filter()吗?为什么不使用更多的Pythonic列表理解?

例:

>>> DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> threshold = 3
>>> long_dna = [dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold]
>>> long_dna
['ATAT', 'GTGTACGT', 'AAAAGGTT']

>>> threshold = 4
>>> [dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold]
['GTGTACGT', 'AAAAGGTT']
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是可以将它转换为生成器,这可以提供改进的内存和执行,具体取决于您的应用程序,例如,如果您有大量的DNA序列,并且您想迭代它们,将它们作为列表实现一次消耗大量内存.等效发电机只需要用圆括号替换方[]括号():

>>> long_dna = (dna_seq for dna_seq in DNA_list if len(dna_seq) > threshold)
<generator object <genexpr> at 0x7f50de229cd0>
>>> list(long_dna)
['GTGTACGT', 'AAAAGGTT']
Run Code Online (Sandbox Code Playgroud)

在Python 2中,这种性能改进不是一种选择,filter()因为它返回一个列表.在Python 3中,filter()返回一个更类似于生成器的过滤器对象.


the*_*eye 5

您可以is_long返回一个可以接受的函数dna,就像这样

>>> def is_long(length):
...     return lambda dna: len(dna) > length
... 
Run Code Online (Sandbox Code Playgroud)

然后filter像这样使用它

>>> filter(is_long(3), DNA_list)
['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> filter(is_long(4), DNA_list)
['GTGTACGT', 'AAAAGGTT']
Run Code Online (Sandbox Code Playgroud)

注意:不要使用is运算符来比较布尔值或数字。而是尽可能地依赖数据的真实性。因此,就您而言,您可以像这样编写第二个版本

if get_long(element, 3):
    long_dna_loop2.append(element)
Run Code Online (Sandbox Code Playgroud)

引用PEP-8 中的编程建议

不要使用 == 将布尔值与 True 或 False 进行比较。

 Yes:   if greeting:
 No:    if greeting == True:
 Worse: if greeting is True:
Run Code Online (Sandbox Code Playgroud)