锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Python学习笔记(11)-函数式编程

时间:2023-03-12 01:00:00 12dsef功率继电器

1.高阶函数

定义函数时,以函数为参数,可称为高级函数,使用高级函数编程为函数编程。

1.1变量可以指向函数,函数名也是变量

在python中,函数名也是变量,在以前的笔记中,函数可以更改名称,例如。

代码:

my = abs  # 函数名abs指向abs()函数,变量my也指向abs()函数 print(abs(-4))   print(my(-4)) 

结果:

4 4 

若函数名(即变量)abs指向其他数据或函数名abs如果删除了指向,原来的abs()函数名不能再使用函数abs例如

代码:

abs = 1  # 变量abs已指向整数1,不再指向整数1abs()函数 # del abs 此句是删除abs的指向 print(abs(-4))  # 变量abs不再指向abs()函数了 

结果:

TypeError: 'int' object is not callable #  NameError: name 'abs' is not defined 

因此,在定义函数时,变量可以用作参数。同样,函数名也可以用作将函数传输到另一个函数。

代码:

# 定义平方函数 def square(number):     return number ** 2   # 根据传输的函数逻辑计算两个数的结果和 def test(x, y, method):     print(method(x)   method(y))   test(1, 3, square)  # 传入寻求平方的逻辑 test(1, -3, abs)    # 寻求绝对值的逻辑,注意是abs()函数的函数名,即变量abs

结果:

10 4 

1.2map()redued()函数的使用

map()函数接收两个参数,第一个是函数,第二个是函数Iterable(可迭代对象),每个元素都运行函数,并将结果作为一个Iterator返回(注意:Iterator输出存储结果不能直接打印)

例如,请求列表中每个数的3次方(事实上,循环也可以实现,但可以使用map()函数更直观方便,更容易理解)

代码:

def cube(x):  # 定义计算三次功率的函数     return x ** 3   nums = [1, 2, 3, 4, 5] result = list(map(cube, nums))  # 使用map通过函数传输计算函数和数据list将对象变成列表对象 print(result)

结果:

[1, 8, 27, 64, 125] 

reduce()函数还接收两个参数,第一个是函数,函数必须有22个参数,第二个参数是传输的数据。reduce()根据传输函数从数中提取两个元素,并将结果和下一个元素再次作为计算的两个元素。使用reduce()需要导入函数,例如from functools import reduce

代码:

from functools import reduce  # 这个函数没有意义,纯粹是为了练习python语法而已→_→ def prod(L):     def mul(x, y):  # 函数定义了相乘函数         return x * y      return reduce(mul, L)  # 从L中取前两个操作,然后将结果和第三个操作为两个参数,以此类推   print('1*2*3*4 =', prod([1, 2, 3, 4]))

结果:

1*2*3*4 = 24 

map()reduce()结合小栗子,同上,毫无意义,纯粹是为了练习(⊙o⊙)…

将字符串转换为浮点数 strnum '123.456',其实完全可以用float(strnum)

代码:

from functools import reduce  # 导入reduce

strnum = '9876.1234'

def str2float(str=''):
    nums = str.split('.')  # split函数将按照传入的参数分隔字符串并封装到列表中返回
    str1 = nums[0]         # 小数点前的字符串
    str2 = nums[1]         # 小数点后的字符串

    def char2num(s):       # 构造字符转换成数字函数
        return {
    
      '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

    def str2num(x, y):     # 转换成数字后再运算得出整数
        return x * 10 + y

    a = reduce(str2num, map(char2num, str1))
    b = reduce(str2num, map(char2num, str2))
    result = a + b / 10 ** (len(str2))  # 注意是10的n次幂运算
    return result

print(str2float(strnum))

结果:

9876.1234

1.3filter()函数

filter()函数大致同map()函数,也是接收一个函数和一个列表,不同的是,filter()会将每次运行完传入的函数方法后判断,根据TrueFalse来决定是否要保存这个元素,最后返回的也是一个Iterator对象,需要用list()才能显示出来。例如

代码:

def saveS(s):  # 传入的字符创中如果有s返回True,否则返回False
    return 's' in s


L = ['abc', 'dsef', 'asdf', 'ee', 'sht']

print(list(filter(saveS, L)))  # 返回True时保留

结果:

['dsef', 'asdf', 'sht']

e.g. 用filter()求素数,使用方法逻辑是埃氏筛法

代码:

# 初始化一个序列,从3开始的奇数(偶数不是素数)
def initNumber():
    n = 1
    while True:
        n += 2
        yield n


# 定义一个筛选函数,能被n整除的返回False,不能整除的返回True
def check(n):
    return lambda x: x % n > 0


def getPrime(maxNum):
    yield 2  # 生成器返回第一个素数
    init = initNumber()  # 调用初始化函数 3,5,7,9,11,13,15,17,19,21...
    while True:
        n = next(init)  # 取得初始化的第一个数3
        if n < maxNum:
            yield n  # 生成器返回第一个数3(第一个数总是素数)
            init = filter(check(n), init)  # 过滤3的倍数5,7,11,13,17,19... 如此循环
        else:
            break


print(list(getPrime(100)))

结果:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

1.4sorted()函数

在笔记(2)中,已经记录了对列表的排序,里面的sorted()可以只传入列表进行临时排序,也可再添加按照相应的逻辑来排序(即传入函数名,使用命名关键字key=xxx) 例如

代码:

L = ['a', 'c', 'M', 'F', 'e']
print(sorted(L))  # 原列表排序
print(sorted(L, reverse=True))  # 列表反序
print(sorted(L, key=str.lower))  # 按照元素的字母的ASCII码(无视大小写,函数名也可换做str.upper)

结果:

['F', 'M', 'a', 'c', 'e']
['e', 'c', 'a', 'M', 'F']
['a', 'c', 'e', 'F', 'M']

2.返回函数和闭包

函数不仅可以作为参数传递,还可作为返回值来返回,例如

代码:

def getInfo(name):  # 函数A
    def getAge(age):  # 函数A中定义了函数B
        return 'name=' + name + ',age=' + str(age)

    return getAge  # 返回函数,即指向函数B的变量(函数名)


test1 = getInfo('zhangsan')  # 调用getInfo函数,返回一个函数,即之前定义好的getAge()函数,用test1指向它
test2 = getInfo('lisi')
print (test1(22))  # 再调用返回的函数
print (test2(22))

结果:

name=zhangsan,age=22
name=lisi,age=22

什么是闭包呢?简单的讲就是调用函数A,而A返回了一个函数B,并且B引用了传递给A的参数(或者是A内部定义的局部变量),这个函数B就叫做闭包,这个参数就是闭包的自由变量

如上述的代码中,调用getInfo()时传递的参数(即自由变量)是不同的,即使闭包getAge()调用的时候test1(22)传入相同的参数,结果仍是不同的。

需要注意的是:返回的闭包函数没有立即执行,而是在调用(例如test1(22))的时候才会执行,举个栗子

代码:

def count():  # 函数A
    fs = []  # 创建一个空列表
    for i in range(1, 4):  # 循环3次,i是A的变量
        def f():  # 函数A中定义的函数B,引用了A的变量i
            return i * i  # 返回表达式(也是个函数),并没有直接调用

        fs.append(f)  # 添加到列表中,循环完毕后i的值已经是3
    return fs


f1, f2, f3 = count()  # f1,f2,f3分别指向列表中的3个函数
print (f1())  # 分别调用函数,注意,此时调用的时候直接从第五行代码开始执行,此时的i已经是3
print (f2())
print (f3())

结果:(结果不是1,4,9,可在debug模式下看执行步骤)

9
9
9

由此可见,在闭包函中的自由变量,或者是调用的A的局部变量尽量不要使用动态变化的。

3.匿名函数

先看代码,求一个数的3次方,可用如下代码

代码:

L = [1, 2, 3, 4, 5]


def cube(x):
    return x ** 3


print (list(map(cube, L)))

结果:

[1, 8, 27, 64, 125]

如果某些函数只调用一次,可以用lambda表达式来构造匿名函数,不用再显示的定义函数,如下

代码:

L = [1, 2, 3, 4, 5]

print (list(map(lambda x: x ** 3, L))) 

结果:

[1, 8, 27, 64, 125]

lambda x: x ** 3实际上就是上边定义的函数cube,第一个x是参数(可不写,即为无参函数),后边的是函数逻辑,整个表达式返回一个函数变量,匿名函数也可作为返回值。

4.装饰器

在定义好的函数运行期间,不修改此函数,动态地给该函数增添功能,即为装饰器Decorator,说白了就是传递函数和返回函数的运用,下边是个最简单的例子,例如。详细请看

代码:

def deco(fun):
    print('---运行之前---')
    fun()
    print('---运行之后---')


def myfun():  
    print('运行了函数')


deco(myfun)  # 将函数作为参数传递

结果:

---运行之前---
运行了函数
---运行之后---

5.偏函数

如果调用某个函数的时候,该函数的参数过多,需要简化,可以使用functools模块的partial,例如

int()可以将字符串转换成整数,只传入字符串时,默认按照十进制转化,若添加base参数,则按照所传的进制计算

代码:

print(int('1234567'))
print(int('1234567', base=8))
print(int('1234567', base=16))

结果:

1234567
342391
19088743

除了每次都传入base参数,还可用partial,例如

代码:(其实就是外部更改了函数参数默认值)

import functools

int2 = functools.partial(int, base=2)  # int函数外固定其参数base默认值是2
print(int2('101010001001'))  # 每次调用无需再传入参数base
print(int2('101101'))
print(int2('101101', base=8)) # 当手动传入base参数的时候,按照传入的数据计算

结果:

2697
45
33345
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章