Python学习笔记|高阶函数

Bruce
2023-12-19 / 0 评论 / 10 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年12月24日,已超过333天没有更新,若内容或图片失效,请留言反馈。

一、高阶函数基础

(一)、变量可以指向函数

abs
<function abs(x, /)>
abs(-10)
10
x = abs(-10)
print(x)
10
f = abs
print(f)
<built-in function abs>
# 变量f指向了一个函数
# f = abs
# print(f(-10))

(二)、函数名也是变量

# abs指向数值后,就无法
# abs = 10
# abs(-10)

(三)、传入函数

变量可以指向函数,函数的参数能接受变量,那么一个函数的变量就能指向另一个函数。这种函数即为高阶函数。

def add(x,y,f):
    return f(x) + f(y)
add(-5,5,abs)
10

二、Map函数

map函数接受两个参数,一个是函数,一个是Iterable(可迭代对象),map将传入的函数依次作用于序列中的每个元素,并把结果作为新的Iterator返回。

def f(x):
    return x * x
r = map(f,[1,2,3,4,5,6,7,8,9,10])
list(r)
# 输出结果:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

上面这个例子也可以使用循环实现:

def f(x):
    return x * x
L =[]
for i in range(1,11):
    L.append(f(i))
print(L)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

但用循环的缺点在于稍微有些抽象,不如直接用map函数形象。

三、reduce函数

reduce函数把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce()函数把结果和序列的下一个元素做累计计算。

from functools import reduce
def add(x,y):
    return x + y
reduce(add, [1,3,5,7])
16

将序列[1,3,5,7]变换为整数1357

from functools import reduce
def str2int(x,y):
    return x *10 + y
reduce(str2int, [1,3,5,7])
1357

str转换为int函数

from functools import reduce

def str2int(x,y):
    return x *10 + y
    
def convert(i): 
    digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    return digits[i]

reduce(str2int, map(convert, '1357'))
1357

整理为一个str2int函数:

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 str2int(n):
    def s2t(x,y):
        return x *10 + y
    def convert(n): 
        return digits[n]
    return reduce(s2t, map(convert, n))
str2int('255')
255

使用lambda函数可以进一步简化:

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 convert(i): 
    return digits[i]

def str2int(i):
    return reduce(lambda x, y: x * 10 + y, map(convert, i)) #使用lambda x, y: x * 10 + y替换了str2int(n)函数
str2int('2566')
2566

利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']:

def normalize(names):
        return names[0].upper() + names[1:].lower()

names = ['adam', 'LISA', 'barT']

list(map(normalize, names))
['Adam', 'Lisa', 'Bart']

请编写一个prod()函数,可以接受一个list并利用reduce()求积:

# def prod(*num):
#     n = 1
#     for i in L:
#         n = n * i
#     return n
# L = [1,2,3,4]  
# print(prod(*L))

def prod(num):
    return reduce(lambda x, y: x*y, num)
L = [1,2,3,4]
print(prod(L))
24

利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:

from functools import reduce


def str2float(s):
    # 获取小数点的索引位置
    period_index = s.index(".")

    # 获取小数点左侧的字符
    left_char = s[:period_index]

    # 获取小数点右侧的字符
    right_char = s[period_index + 1:]

    # 定义字符串转数字的函数convert()
    def convert(i):
        digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
        return digits[i]

    # 转换小数点左侧数字
    left_sum = reduce(lambda x,y: x * 10 + y, map(convert, left_char))

    # 转换小数点右侧数字
    mid_num = reduce(lambda x,y: x * 10 + y, map(convert, right_char))
    right_sum = mid_num / 10 ** len(right_char)

    return left_sum + right_sum
    
print(str2float('123.456'))
python123.456

四、filter函数

类似map(),filter()接收一个函数和序列,将传入的函数依次作用于每个元素,然后根据返回时True还是False决定保留还是丢弃该元素。

例如在一个list中,删掉偶数,只保留奇数,可以这么写:

def is_odd(n):
    return n % 2 == 1
list(filter(is_odd, [1,2,4,5,6,9,10,15]))
[1, 5, 9, 15]

把一个序列中的空字符串删掉,可以这么写:

def not_empty(s):
    return s and s.strip()
list(filter(not_empty,['A','','B', None, 'C','   ']))
['A', 'B', 'C']

filter()函数返回的是一个Iterator,是一个惰性序列,因此要强迫filter()完成计算结果,就需要用list()函数获得所有的结果并返回list.

# 筛选素数

# 构造一个从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) # 构造新序列

# primes()是一个无限序列,所以调用的时候需要设置一个退出循环条件:
# 打印100以内的素数
for n in primes():
    if n < 100:
        print(n)
    else:
        break
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

三、Sorted函数

soted()函数是Python内置函数,可以对list进行排序。

sorted([36,5,-12,9,21])
[-12, 5, 9, 21, 36]

key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。对比原始的list和key = abs处理过

list = [36, 5, -12, 9, -21]
key = [36, 5, 12, 9, 21]

默认情况下,对字符串排序,是按照ASCII的大小比较的,由于'Z' < 'a',结果,大写字母Z会排在小写字母a的前面。

sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']

忽略大小写,按照字母序排序。用一个key函数把字符串映射为忽略大小写排序即可。忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再比较。

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

反向排序,不必改动key函数,可以传入第三个参数reverse=True

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

小结:sorted()函数排序的关键在于实现一个映射函数。

# 请用sorted()对上述列表分别按名字排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
sorted_list = sorted(L, key = lambda x: x[0])
print(sorted_list)
[('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
# 请用sorted()对上述列表分别按成绩排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
sorted_list = sorted(L, key = lambda x: x[1])
print(sorted_list)
[('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Adam', 92)]
0

评论 (0)

取消