在python中将带有两个参数的函数传递给filter()
鉴于以下清单:在python中将带有两个参数的函数传递给filter(),python,list,python-2.7,Python,List,Python 2.7,鉴于以下清单: DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT'] 我想筛选长度超过3个字符的字符串。我通过以下代码实现这一点: 对于for循环: long_dna = [] for element in DNA_list: length = len(element) if int(length) > 3: long_dna.append(element) print long_dna def get_long(dna
DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT']
我想筛选长度超过3个字符的字符串。我通过以下代码实现这一点:
对于for循环:
long_dna = []
for element in DNA_list:
length = len(element)
if int(length) > 3:
long_dna.append(element)
print long_dna
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
但我希望我的代码更加通用,以便以后可以过滤任意长度的字符串,因此我使用函数和for循环:
long_dna = []
for element in DNA_list:
length = len(element)
if int(length) > 3:
long_dna.append(element)
print long_dna
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
我想使用filter()
实现同样的通用性,但我无法实现这一点。如果我使用上述函数get_long()
,当我将其与filter()
一起使用时,我就无法向其传递参数。这是不可能的,还是有办法解决
针对特定情况,使用filter()
的我的代码:
def is_long(dna):
return len(dna) > 3
long_dna_filter = filter(is_long, DNA_list)
使用
lambda
提供阈值,如下所示:
filter(lambda seq: get_long(seq, 3),
dna_list)
您可以使
is_long
返回一个函数,该函数可以接受dna
,如下所示
>>> def is_long(length):
... return lambda dna: len(dna) > length
...
>>> filter(is_long(3), DNA_list)
['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> filter(is_long(4), DNA_list)
['GTGTACGT', 'AAAAGGTT']
if get_long(element, 3):
long_dna_loop2.append(element)
然后在过滤器中使用它,如下所示
>>> def is_long(length):
... return lambda dna: len(dna) > length
...
>>> filter(is_long(3), DNA_list)
['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> filter(is_long(4), DNA_list)
['GTGTACGT', 'AAAAGGTT']
if get_long(element, 3):
long_dna_loop2.append(element)
注意:不要使用is
运算符来比较布尔值或数字。相反,要尽可能依赖数据的真实性。所以,在你的情况下,你可以这样写你的第二个版本
>>> def is_long(length):
... return lambda dna: len(dna) > length
...
>>> filter(is_long(3), DNA_list)
['ATAT', 'GTGTACGT', 'AAAAGGTT']
>>> filter(is_long(4), DNA_list)
['GTGTACGT', 'AAAAGGTT']
if get_long(element, 3):
long_dna_loop2.append(element)
引用
不要使用==将布尔值与True或False进行比较
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
您试图做的是:您有一个具有多个参数的函数(在本例中为2),并且希望从该函数派生一个具有一个或多个固定参数的函数,然后可以将其传递到过滤器
有些语言(特别是函数式语言)具有“内置”此功能。在python中,您可以使用lambdas来实现这一点(如其他人所示),也可以使用。特别是:
partial()用于partial函数应用程序,它“冻结”函数参数和/或关键字的某些部分,从而生成具有简化签名的新对象。例如,partial()可用于创建一个可调用函数,其行为类似于int()函数,其中基参数默认为两个:
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
因此,您可以:
filter(functools.partial(get_long, treshold=13), DNA_list)
是否需要使用过滤器()
?为什么不使用一个更具python风格的列表理解呢
例如:
>>> 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']
这种方法的优点是,将其转换为生成器非常简单,生成器可以根据您的应用程序提供更好的内存和执行,例如,如果您有很多DNA序列,并且希望对它们进行迭代,将它们实现为列表将一次性消耗大量内存。等效生成器只需将方括号[]
替换为圆括号()
:
>>long_dna=(如果len(dna_seq)>阈值,则dna_seq代表dna_seq在dna_列表中)
>>>列表(长)
['GTGTACGT','AAAAGGTT']
在Python2中,filter()
不能选择这种性能改进,因为它返回一个列表。在Python 3中,filter()
返回更类似于生成器的筛选器对象。以下是使用lambda
的更多方法。第一个使用默认关键字参数来保存所需的长度。第二个简单地将所需的长度嵌入lambda
主体中
#Create a list of strings
s = 'abcdefghi'
data = [s[:i+1] for i in range(len(s))]
print data
thresh = 3
print filter(lambda seq, n=thresh: len(seq) > n, data)
print filter(lambda seq: len(seq) > 5, data)
输出
['a', 'ab', 'abc', 'abcd', 'abcde', 'abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']
['abcd', 'abcde', 'abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']
['abcdef', 'abcdefg', 'abcdefgh', 'abcdefghi']
在第一个示例中,您还可以执行以下操作:
print filter(lambda seq, n=3: len(seq) > n, data)
类似地,在第二个示例中,可以用局部(或全局)变量替换literal5
,例如:
thresh = 5
print filter(lambda seq: len(seq) > thresh, data)
您始终可以创建一个callable,该callable返回一个适合于filter
进行比较的callable,如下例所示:
def main():
dna_list = ['A', 'CA', 'TGATGATAC', 'GGGTAAAATC', 'TCG', 'AGGTCGCT', 'TT',
'GGGTTGGA', 'C', 'TTGGAGGG']
print('\n'.join(filter(length_at_least(3), dna_list)))
def length_at_least(value):
return lambda item: len(item) >= value
# length_at_least = lambda value: lambda item: len(item) >= value
if __name__ == '__main__':
main()
你可以有一个更一般的情况
由于函数是python中的一个对象,因此可以创建另一个函数,返回所需的函数。
def f(threshhold):
def g(x):
return len(x)>threshhold
return g #return a function
this_function = f(3)
DNA_list = ['ATAT', 'GTGTACGT', 'AAAAGGTT','AAA','AAAA']
filter(this_function, DNA_list)
output: ['ATAT', 'GTGTACGT', 'AAAAGGTT', 'AAAA']
g是您真正想要的,f是创建它的函数。我使用了不同的解决方案,使用了内部函数和非局部作用域,如下所示。我已经修改了这个原始代码以便于理解,因为我的代码是不同的
希望这有帮助。:)
就我个人而言,无论如何,我发现列表理解比filter
应用程序更容易阅读。