Python基础——高阶函数之Python内建函数(一)

什么是高阶函数?首先我们先明确一点函数名是什么:函数名其实就是指向函数的变量,看上去有点抽象,用几行代码描述一下:

>>> def sum(n):
...     result = 0
...     for i in range(1, n + 1):
...         result += i
...     return result
...
>>> sum(17)
153
>>> sum = 73
>>> sum(17)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

sum其实就是个变量,它可以指向任何类型。定义一个sum的函数实质是定义了一个sum变量然后指向一个函数,由于python动态语言的特性,sum可以重新指向另外一个类型例如代码中的整数(73),此时再次调用sum(17)就会报错,因为sum现在已经不是指向求和函数了。
既然变量可以指向函数,且函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种形式就称之为高阶函数,用几行代码描述:

>>> def square_sum(x, y, f):
...     return f(x) + f(y)
...
>>> f = lambda x: x ** 2
>>> square_sum(3, 4, f)
25

1. map

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数一次作用到序列的每个元素,并把结果作为新的Iterator返回。示例:把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。

>>> standardlize = map(lambda s: s.title(), ['adam', 'LISA', 'JAcK', 'RosE'])    # standardlize是一个Iterator
>>> list(standardlize)    # 通过list()函数让它把每个序列都计算出来并返回一个list
2. reduce

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数。例如:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)。示例:求阶乘。

>>> from functools import reduce
>>> def multiply(x, y):
...     return x * y
...
>>> seq = [1, 2, 3, 4, 5]
>>> reduce(multiply, seq)

示例1:把序列[1, 2, 3, 1, 5]转换成整数12315。

reduce(lambda x, y: x * 10 + y, [1, 2, 3, 1, 5])

示例2:将字符串‘12315’转换成整数12315

>>> DIGITS = {str(x): x for x in range(10)}
>>> reduce(lambda x, y: x * 10 + y, map(lambda x: DIGITS[x], '12315'))

示例3:将字符串‘123.15’转换成浮点数123.15

from functools import reduce
import re

DIGITS = {str(x): x for x in range(10)}


def str2float(s):
    # 计算除数部分
    divisor = pow(10, len(s.split('.')[1]))
    # 将字符串中的小数点去掉并转换成整数
    s = re.sub('\.', '', s)
    temp_num = reduce(lambda x, y: x * 10 + y, map(lambda s: DIGITS[s], s))
    return temp_num / divisor
3. filter
filter()函数用于过滤序列,接收一个函数和序列,将传入的函数一次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。返回一个Iterator

示例1:用filter求素数。埃氏筛法:1)列出从2开始的所有自然数,构造一个序列。2)取序列的第一个数2,它一定是素数,然后用2把xulie序列的2的倍数筛掉。3)取新序列的第一个数3,它一定是素数,然后用3把序列3的倍数筛掉。4)取序列的第一个数5然后用5把序列的5的倍数筛掉。不断筛下去,就可以得到所有素数。

# 奇数生成器
def generate_odd():
    n = 3
    while True:
        yield n
        n += 2


# 过滤函数,过滤掉digit的倍数
def f(digit):
    return lambda x: x % digit > 0


# 素数生成器
def generate_primes():
    yield 2
    it = generate_odd()
    while True:
        digit = next(it)
        yield digit
        it = filter(f(digit), it)   # 可以过滤掉digit的倍数
        # it = filter(lambda x: x % digit > 0, it)  #过滤不掉digit的倍数,为什么?
        # 这里是由于对于lambda来说,digit是一个新定义的变量,其默认值为0。因此不会过滤掉任何数。
        # 将其改成lambda x, y=digit: x % y > 0


def generate_some_primes(n):
    count = 0
    for prime in generate_primes():
        if count < n:
            print(prime, end=' ')
            count += 1
        else:
            break


generate_some_primes(73)

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

# 筛选1~1000的回数
>>> list(filter(lambda digit: str(digit) == str(digit)[::-1], range(1, 1000)))
[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, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
4. sorted

sorted可以序列进行简单的排序:

>>> sorted('sadf')
['a', 'd', 'f', 's']

另外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序:

>>> 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']

示例:按成绩从高到低排序:

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
# 注意:由于是从高到底,这里返回成绩的负数
def by_score(t):
    return -t[1]
L2 = sorted(L, key=by_score)
print(L2)

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭