文章背景: 最近在学习廖雪峰老师的Python文章,其中有个章节讲到的是filter()函数,该函数用于过滤序列。在学习过程中,也顺带巩固了其它的知识点,在此进行相应的整理。
Python版本:Python 3.7
1 filter()函数
2 示例代码
2.1 保留奇数
2.2 删除序列中的空字符串
2.3 采用函数filter()求数
2.4 采用函数filter()求回数
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。
该函数接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新序列中。
语法:filter(function, iterable)
def is_odd(n):
return n % 2 == 1
series = [1, 2, 4, 5, 6, 9, 10, 15]
print(list(filter(is_odd, series)))
运行结果:
[1, 5, 9, 15]
def not_empty(s):
return s and s.strip()
series = ['A', '', 'B', None, 'C', ' ']
print(list(filter(not_empty, series)))
运行结果:
['A', 'B', 'C']
前段代码块的功能是删掉列表中的空字符串,包括None,""和" "。注意函数not_empty()中的代码s and s.strip()
。
(1)在Python3中,None,0,空字符串,空列表,空字典、空集合都返回False。
(2)针对逻辑运算符and
,对于表达式x and y
,这里需要这样理解:布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。
x and y
等价于:x if not x else y
。请看下面的例子。
x = 0
y = 1
print("x and y =", x and y)
print("x AND y =", x if not x else y)
运行结果:
x and y = 0
x AND y = 0
在运行 and 运算符时,从左到右 进行逻辑运算 (判定输出结果)。一旦遇到 bool 逻辑为 False的值,则立刻返回该值,且不再往后运算;否则,所有元素的 bool 逻辑值均为 True,and 运算符将返回 最后一个值。
(3)回到本节开头的代码s and s.strip()
。对于元素None
,如果运行方法strip(),程序将报错,'NoneType' object has no attribute 'strip'
。所幸的是None本身返回False。因此,对于元素None
, s.strip()
并不会运行,从而也不会报错。
另外,对于带两个空格的变量' '
,该变量返回的布尔值是True
,采用s.strip()方法后,得到的是空字符串(布尔值为False),所以,代码行s and s.strip()
返回的布尔值也是False。
test = " "
print(bool(test))
print(bool(test.strip()))
运行结果:
True
False
计算素数的一个方法是埃氏筛法,它的算法可以这么理解:
(1)首先,列出从2
开始的所有自然数,构造一个序列。
(2)取序列的第一个数2
,它一定是质数,然后用2
把序列中2
的倍数筛掉。
(3)取新序列的第一个数3
,它一定是质数,然后用3
把序列中3
的倍数筛掉。
(4)取新序列的第一个数5
,然后用5
把序列中5
的倍数筛掉。
(5)取新序列的第一个数7
,然后用7
把序列中7
的倍数筛掉。
如此,不断筛下去,就可以得到所有的质数。
基于上述的算法,得到的代码块如下:
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一个数
yield n
it = filter(_not_divisible(n), it) # 构造新序列
# 打印20以内的素数:
for item in primes():
if item < 20:
print(item, end=" ")
else:
break
运行结果:
2 3 5 7 11 13 17 19
(1) 函数_odd_iter()
中,由于存在yield
关键字,因此,得到的是一个生成器,构造的是一个从3开始的奇数序列,并且它是无限序列。关于yield用法的解析,请查阅文末的参考资料[6]。
(2) 函数_not_divisible(n)
中,构造的是一个筛选函数。其中,存在参数n,因为每次的除数都在变化。
(3) 函数primes()
中,同样存在yield
关键字,因此,得到的也是一个生成器,一开始返回质数2,后来通过filter()
不断产生筛选后新的序列,并且也是一个无限序列。
(4)由于通过函数prime()得到的是一个无限序列,所以调用时需要设置一个退出循环的条件。本代码块要实现的目标是:输出20以内的所有质数。
(5)在for循环中,一开始先进入函数primes(),运行到代码行yield 2
,返回数字2,退出函数primes()。所以一开始输出的数字是2。然后继续进入函数primes(),接着代码yield 2
,运行之后的代码。将函数_odd_iter()
赋值给变量it
,得到一个生成器(从3开始的奇数序列)。
(6) 然后进入while循环,针对生成器it
,使用next方法。这个时候,进入函数_odd_iter()
,返回数字3,退出函数_odd_iter()
。继续回到函数primes()
中,将3赋给变量n。然后返回数字3,退出函数primes()。所以第二个输出的数字是3。
(7)继续进入函数primes()
,接着代码yield n
,运行之后的代码。目前变量n的值是3,变量it
是从3开始的奇数序列,通过filter筛选(去掉3的倍数)后,得到的是5开始的序列,将该序列重新赋给变量it
。在while循环内继续运行。针对生成器it
,使用next方法。这个时候,返回变量it
这个生成器的第一个值,也就是5,将5赋给变量n。然后返回数字5,退出函数primes()。所以第三个输出的数字是5。
(8) 继续进入函数primes()
,接着代码yield n
,运行之后的代码。目前变量n的值是5,变量it
是从5开始的序列,通过filter筛选(去掉5的倍数)后,得到的是7开始的序列,将该序列重新赋给变量it
。继续在while循环内继续运行。针对生成器it
,使用next方法。这个时候,返回变量it
这个生成器的第一个值,也就是7,将7赋给变量n。然后返回数字7,退出函数primes()。所以第四个输出的数字是7。
(9)如此反复,直到返回的变量item大于20时,退出for循环。
回数是指从左向右读和从右向左读都是一样的数,例如12321
,909
。
获取100~200范围内的所有回数,可以通过下面的代码块实现。
def is_palindrome(n):
return str(n) == str(n)[::-1]
output = filter(is_palindrome, range(100, 200))
print(list(output))
运行结果:
[101, 111, 121, 131, 141, 151, 161, 171, 181, 191]
获取某个字符串倒数后的结果,可以通过切片器(Slicing)实现。
var_st = "python"
string_length = len(var_st)
print(var_st[0:string_length:1])
print(var_st[string_length::-1])
print(var_st[string_length-1::-1])
print()
print(var_st[string_length-2::-1])
print(var_st[::-1])
运行结果:
python
nohtyp
nohtyp
ohtyp
nohtyp
参考资料:
[1] filter(https://www.liaoxuefeng.com/wiki/1016959663602400/1017404530360000)
[2] Python3 filter() 函数(https://www.runoob.com/python3/python3-func-filter.html)
[3] Python 逻辑判断True/False的坑(https://www.biaodianfu.com/python-true-false.html)
[4] Python 运算符(https://www.runoob.com/python/python-operators.html)
[5] 详解 逻辑运算符 (and / or / not) + 布尔逻辑 (bool)(https://blog.csdn.net/qq_39478403/article/details/105654170#2.2%20and%20%E2%80%94%E2%80%94%20bool%20%E2%80%9C%E4%B8%8E%E2%80%9D%20%E9%80%BB%E8%BE%91%E8%BF%90%E7%AE%97%E7%AC%A6)
[7] How do you reverse a string in Python(https://www.educative.io/edpresso/how-do-you-reverse-a-string-in-python)