Python学习笔记(四)—— 高阶函数map/reduce/filter/sorted函数介绍及练习

        函数式编程:函数式编程就是一种抽象程度很高的编程范式,它的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数,Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

 高阶函数

高阶函数:一个函数接收另一个函数作为参数,这个函数称为高阶函数。
【附基础知识:变量可以指向函数;函数名看可以是变量;

即:

>>> abs(-10)
10
>>> f = abs #变量指向函数
>>> f(-10)
10
>>> abs = 10  #函数名可以作为变量
>>> abs(-10) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
实际上函数名只是一个指向函数的变量。】

map()/reduce()

    map( func , list/str... )函数输入参数一个为函数,另一个为可迭代的变量。该函数将第一个参数的函数分别作用于第二个参数的每一个元素,并把结果作为新的可迭代变量返回。如:

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
      reduce()与map()相似,只是它把结果继续和序列中的下一个元素做函数运算,即将结果作为传入参数一中的函数的参数。
>>> from functools import reduce
>>> def add(x, y):
...     return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25

注意: 使用reduce() 需要 from functools import reduce

廖雪峰网站对应练习答案:

#练习1

#利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456: 
from functools import reduce
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9};
def str2float(s):
    if '.' in s:
        n = s.index('.');        
    N = len(s)- n -1 ;
    s = s[:n]+s[n+1:]; 
    def str2num(s):
            return DIGITS[s];
    def fn1(x,y):
        return x * 10+y;
    num = reduce(fn1, map(str2num,s));
    while N>0:
        num = num * 0.1;
        N = N -1;
    return num;
#测试
print('str2float(\'123.456\') =', str2float('123.456'))
if abs(str2float('123.456') - 123.456) < 0.00001:
    print('测试成功!')
else:
    print('测试失败!')


filter() 

    filter ( func, list... ) 和map类似,它也是接收一个函数与一个序列,只不过这个函数的返回值是True或False,一次判断这个序列中的元素是否符合条件,然后选择保留还是丢弃。例子:

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]
用filter求素数
计算素数的一个方法是 埃氏筛法,它的算法理解起来非常简单:
首先,列出从2开始的所有自然数,构造一个序列:
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
取序列的第一个数2,它一定是素数,然后用2把序列的2的倍数筛掉:
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
取新序列的第一个数3,它一定是素数,然后用3把序列的3的倍数筛掉:
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...
不断筛下去,就可以得到所有的素数。
用Python来实现这个算法,可以先构造一个从3开始的奇数序列:
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) # 构造新序列

# 打印1000以内的素数:
for n in primes():
    if n < 1000:
        print(n)
    else:
        break

【附:函数lambda介绍:

>>> g = lambda x:x+1;
>>> g(1)  #输出为 2
>>> g(2)  #输出为 3
#上面语句相当于
def g(x):
     return x+1
可以这样认为,lambda作为一个表达式,定义了一个匿名函数,上例的代码x为入口参数,x+1为函数体】

廖雪峰网站对应练习答案:

#练习
#回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数:

#def is_palindrome(n):#【方法1】
#    s = str(n); #数字转字符串
#    l = len(s)//2; #得到中间位数 再头尾比较
#    for x in range(0,l):
#        if(s[x]==s[-(x+1)]):
#            continue;
#        else:
#            return False;
#    return True;
def is_palindrome(n):#【方法2】
    s = str(n); #数字转字符串
    return s == s[::-1]; #愿字符串与倒序字符串比较

# 测试:
output = filter(is_palindrome, range(1, 1000))
print('1~1000:', list(output))
if list(filter(is_palindrome, range(1, 200))) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]:
    print('测试成功!')
else:
    print('测试失败!')

sorted() 

sorted( list... , key = func ,reverse = False)可以对序列进行排序,默认升序排序,如果要改为升序,可以传入函数reverse确定是否反转;也可以通过key函数 key = 对 list 每一个元素进行作用后再排序。

注意:这个函数只在排序的时候作用,不改变原来序列的值。

如:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
['about', 'bob', 'Credit', 'Zoo']

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']


廖雪峰网站对应练习答案:

#假设我们用一组tuple表示学生名字和成绩:
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
#请用sorted()对上述列表分别按名字排序:
def by_name(t):
    return t[0];
    
#按成绩从高到低排序:
def by_score(t):
    return t[1];
   
L2 = sorted(L, key=by_name)
print(L2)
L3 = sorted(L, key=by_score,reverse = True)
print(L3)

猜你喜欢

转载自blog.csdn.net/qq_36999901/article/details/80277174