python中raw函数_Python基础 | 函数式编程和高阶函数

函数式Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计 => 函数就是面向过程的程序设计的基本单元

函数式编程就是一种抽象程度很高的编程范式(范式就是标准的意思),存粹的函数式编程语言编写的函数没有变量 => 任意一个函数,只要输入是确定的,输出就是确定的,这种存函数我们称之为没有副作用. 而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输

入,可能得到不同的输出,因此,这种函数是有副作用的.

函数式编程的一个特点就是 => 允许把函数本身作为参数传入另一个函数,还允许返回一个函数. (函数作为参数,函数作为返回值)

高阶函数

两个概念

变量可以指向函数 2. 函数名也是变量

变量可以指向函数

# 以python内置的abs()为例子

>>> print(abs(-10))

10

# 如果是只书写abs这个函数变量名,那么是指向的一个函数

>>> abs

# 可见 变量名() 这就是函数调用的方式

>>> x = abs

>>> x(-10)

10

>>> x

函数名也是变量

# 如果把 abs 指向一个int,那么abs这个变量就指向函数了

>>> abs = 10

>>> abs(-10)

Traceback (most recent call last):

File "", line 1, in

TypeError: 'int' object is not callable

>>>

高阶函数示例

(函数式编程的特点就是 => 允许函数作为参数,允许函数为返回值)

把函数作为参数传入,这样的函数就是高阶函数,函数式编程就是指这种高度抽象的编程范式.(高阶函数是函数式编程的一个例子)

Python内建的高阶函数有map、reduce、filter、sorted.

"""

既然变量可以指向函数,函数的参数能接收变量,

那么一个函数就可以接收另外一个函数作为参数,这种函数就成为高阶函数.

"""

def add(x,y,f): # f 传递过来的是指向函数的一个变量

return f(x) + f(y) # abs(-10) + abs(-5)

print(add(-10,-5,abs))

内建高阶函数map的使用

需求: 给定一个序列,需要把该序列的每一项都平方后,返回一个新的序列

1517575-20200309104228775-381734234.png

"""

接收两个参数,一个 函数名, 一个 可变的可迭代对象(注意理解 *,也就是可以传入一个或者传入多个序列)

map(func, *iterables) --> map object

Make an iterator that computes the function using arguments from

each of the iterables. Stops when the shortest iterable is exhausted.

"""

# 1. 将所有一个序列全部平方,放回新的字符串

a = [1,2,3,4,5,6]

# 传统列表生成式 (或者直接写循环)

b = [x**2 for x in a]

print(b)

# 使用map高阶函数

c = map(lambda x:x**2,a) # 注意,返回的是一个map对象(可迭代的对象),要将其list

# 判断一下map()的返回值是不是一个可迭代对象

# 导入这个迭代器,可迭代对象都是其子类

from collections.abc import Iterator

print("map()返回值是否为可迭代对对象: %s" % isinstance(c,Iterator))

# 可迭代对象的话可以直接list() 转变为一个列表

print(list(c))

# 2. map实现将list所有数字转为字符串

# 注意,map是逐项操作,不是列表的拼接,列表拼接的话直接 listA + ListB 即可

b = [str(x) for x in a] # 列表生成式

print(b)

c = map(lambda x:str(x),a)

print(list(c))

# map函数实现传入两个列表,每个数字相加

a = [1,2,3,4]

b = [9,8,7,6]

c = map(lambda x,y:x+y,a,b) # 注意:这里传入了两个序列

print(list(c))

内建高阶函数reduce的使用

reduce主要用于序列的求和

reduce就是把一个函数作用在一个序列[x1,x2,x3...]上,这个函数必须接收两个参数(注意了,是两个参数),reduce把结果继续和序列的下一个元素做累加计算(遍历完这个序列就结束),其效果就是 =>

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

# reduce函数是需要导入的

from functools import reduce

""" 查看官方文档的说明 => (其实说明一般都会给例子)

reduce(function, sequence[, initial]) -> value

Apply a function of two arguments cumulatively to the items of a sequence,

from left to right, so as to reduce the sequence to a single value.

For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates

((((1+2)+3)+4)+5). If initial is present, it is placed before the items

of the sequence in the calculation, and serves as a default when the

sequence is empty.

"""

# 1. 计算一个序列的求和

a = range(1, 11)

res = reduce(lambda x, y: x + y, a)

print("reduce计算累加和: %s " % res)

# 2. 将序列每个元素乘2加上另外一个元素 => 实际上就是计算2进制的方法

a = [1, 1, 1, 1] # 估计结果为15

res = reduce(lambda x, y: x * 2 + y, a)

print(res)

内建高阶函数filter的使用

主要用于函数的过滤

Python 内建的filter()函数用于过滤序列。

和map()类似,filter()也接收一个函数和一个序列。

和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False 决定保留还是丢弃该元素。

"""

filter(function or None, iterable) --> filter object

Return an iterator yielding those items of iterable for which function(item)

is true. If function is None, return the items that are true.

"""

# filter 用法与 map 类似,都是依次作用于每一项

# 根据每一项的 true or false 决定是否保留该项

# 1. 保留序列的奇数,过滤偶数

a = range(1, 11)

b = filter(lambda x: x % 2 != 0, a)

print(list(b)) # 得到过滤的序列

# 2. 把一个字符序列的空字符删除

# 补充知识: None,和 ""(空串) 都是会被判断为false

# " "(3个空格) 是true,所以可以去除首尾空格

a = ['A', '', 'B', None, 'C', ' ']

b = filter(lambda x: x and x.strip(), a)

print(list(b))

内建高阶函数sorted的使用

用于对序列的排序,可以自己规定比较规则

高阶函数 sorted,使用 key=f 实现自定义排序,和Java的Comparator进行比较

"""

sorted(iterable, *, key=None, reverse=False) => 还是查看一下文档靠谱

def sorted(*args, **kwargs): # real signature unknown 真实签名未知

Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the

reverse flag can be set to request the result in descending order.

"""

# 1. sorted对list进行排序 (默认升序)

a = [1, 33, 6, -20, 34]

b = sorted(a) # 返回的是一个新的序列

print("sorted是否在原来序列进行排序: %s" % (id(a) == id(b)))

print(b)

b = sorted(a, reverse=True) # 查看文档才知道 **kwargs 具体是什么

print(b)

# 2. 对字符串进行排序 => 默认按照ASCII码大小排序

# A:65 a:97

# 第一个字符决定不了顺序就看第二个字符,依次下去

a = ["abc", 'ad', "ABC", "D", "d", 'C']

b = sorted(a)

print(b)

b = sorted(a, reverse=True) # 字符串逆序

print(b)

# 3. sorted是一个高阶函数,key=函数,实现自定义排序

# 3.1 对数值列表,按照绝对值大小进行排序

a = [1, 33, 6, -20, 34]

# key = f => 应该是先作用在每一项,然后再去进行比较的

b = sorted(a, key=abs) # 按照绝对值大小进行排序

print(b)

# 3.2 对字符串列表,忽略大小写进行排序

a = ["abc", 'ad', "ABC", "D", "d", 'C']

# 都先把每项统一为大写字母或小写字母

# b = sorted(a, key=str.lower)

b = sorted(a, key=str.upper)

print(b)

匿名函数

Python中使用lambda来声明一个匿名函数

lambda arg1,arg2.... : <表达式>

1. lambda表达式的语法: lambda arg1,arg2,arg3... : <表达式>

其中arg1/arg2/arg3 为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运

算结果。

2. 匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结

果。 => **注意:只能有一个表达式,如果是多个表达式的话就写回正常定义的函数**

# 在python中使用lambda来声明一个匿名函数

# 1. 匿名函数其实也可以使用一个对象来指向 (函数也是一个对象)

f = lambda a, b, c: a + b + c

print(f(1, 2, 3))

# 2. sorted对自定义对象进行排序

# 自定义对象排序的话一定要指定依据什么属性进行比较

# 初始化一个学生类

class Student:

def __init__(self, age, name):

self.name = name

self.age = age

stu1 = Student(11, 'zhangsan')

stu2 = Student(21, 'lisi')

stu3 = Student(31, 'wangwu')

student_list = [stu1, stu2, stu3]

# 按照年龄降序排序

a = sorted(student_list, key=lambda x: x.age, reverse=True)

for x in a:

print("name: %s, age: %d" % (x.name, x.age))

print("=========")

# 按照姓名升序排序

a = sorted(student_list, key=lambda x: x.name)

for x in a:

print("name: %s, age: %d" % (x.name, x.age))

闭包

闭包就是一个函数

闭包是为了后面学习装饰器做铺垫

1. 什么是闭包

闭包其实就是一个函数.

2. 如何创建闭包 (需要满足3个条件)

1) 要有函数的嵌套(外部函数,内部函数)

2)

3. 如何使用闭包

# 1. 使用闭包,完成两个数的和

# 传统函数

def sum(a, b):

return a + b

# 使用闭包

def fOut(a): # 外层函数

def fIn(b): # 内层函数

# 如果内部函数要修改外部函数的变量 => nonlocal

# nonlocal a

# a += 100

return a + b # 内层函数要使用外层函数的变量

return fIn # 外层函数返回内层函数名

# 闭包的使用

f = fOut(100) # f指向外部函数,返回的内部函数

print(type(f)) # f指向是一个函数类型

# 然后再调用内部函数

res = f(200) # 内部函数的返回结果

print("两个数的和: {}".format(res))

# 2. 使用闭包求两点之间的距离

# 传统函数

import math

def getDis(x1, y1, x2, y2):

return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)

res = getDis(0, 0, 1, 1)

print("点(0,0)到点(1,1)的距离: {}".format(res))

# 使用闭包

def getDisOut(x1, y1):

def getDisIn(x2, y2):

return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)

return getDisIn

f = getDisOut(0, 0)

res = f(1, 1) # 函数名加() 就是对函数的调用

print("点(0,0)到点(1,1)的距离: {}".format(res))

闭包的特殊用途,可以在不修改源代码的前提下,添加新的功能

# 闭包的特殊用途

# 闭包可以在不修改源代码的前提下,添加新的功能

# 例子: 添加日志功能

import time # 时间模块

def writeLog(func):

try:

# 以追加方式写入文件

file = open("writeLog.txt",'a',encoding='utf-8')

# 向文件写入日志信息 (访问: 方法名 时间: yyyy-MM-dd)

file.write("访问: {}\t".format(func.__name__))

file.write("时间: {}\n".format(time.asctime()))

except Exception as e:

print(e.args)

finally:

# 关闭资源都是在finally中关闭的

file.close()

def fun1():

# 这样已经修改了这个函数了

# writeLog(fun1)

print("功能1")

def fun2():

# 这样已经修改了这个函数了

# writeLog(fun2)

print("功能2")

# 使用闭包来实现

def fOut(func):

def fIn():

writeLog(func)

func()

return fIn

fIn1 = fOut(fun1)

fIn2 = fOut(fun2)

fIn1() # 进行函数调用

fIn2()

装饰器

在Python中,装饰器就是一种闭包,它可以使闭包的访问方式更简单

其实闭包就是先在内部函数中写要补充的部分,然后再调用一次原来的函数

装饰器的基本使用

# 使用装饰器就是让闭包的使用更加简单

# 使用装饰器完成不修改 fun1() fun2() 函数的源码,添加输出日志信息

import time

def writeLog(func):

try:

file = open("log.txt", "a", encoding="utf-8")

file.write("访问: {}\t".format(func.__name__))

file.write("时间: {}\n".format(time.asctime()))

except Exception as e:

print(e.args)

finally:

file.close()

# 定义闭包函数

def fOut(func):

def fIn():

writeLog(func)

# 这里对func()调用几次就是几次

# 如果没有对func()进行调用,函数直接结束

func()

func()

return fIn

# 使用装饰器在函数之前

# 就相当于把这个函数作为参数传入

# 装饰器装饰后,其实就是等价于 fIn = fOut(fun1),后面调用fun1(),就等同于fIn()

# 执行的是闭包的内容,由闭包来调用fun1

@fOut

def fun1():

print("功能1")

@fOut

def fun2():

print("功能2")

fun1()

fun2()

多个装饰器

# 给foo函数加上多个装饰器

def fOut1(func):

print("fOut1")

def fIn():

print("111111这是装饰器111111")

func()

print("111111这是装饰器111111")

return fIn

def fOut2(func):

print("fOut2")

def fIn():

print("222222这是装饰器222222")

func()

print("222222这是装饰器222222")

return fIn

# 重叠调用

# 是@fOut2先装饰的foo,然后@fOut1再装饰整个函数 => 理解清楚

@fOut1 # 这个@fOut1相当于最外层

@fOut2 # @fOut2为次外层

def foo(): # foo为最内层

print("foo()正在运行")

# 不调用函数,装饰器装饰的时候就调用了闭包的外部函数

# foo()

foo() # 现在是调用嵌套的内部函数

多个装饰器的执行顺序

1517575-20200309180136772-946749389.png

带由参数的装饰器

如果只是参数的个数不同,使用可变参数 *args 解决

# 闭包如果是要装饰一个要传入参数的函数

# 则闭包的内部函数的参数与功能函数一致

# 使用可变参数 *args 来构建通用的装饰器

def fOut(func):

def fIn(*args):

# 有返回值的功能函数是需要return的

return func(*args)

return fIn

@fOut

def sum1(a, b):

return a + b

@fOut

def sum2(a, b, c):

return a + b + c

print(sum1(10, 20)) # 两个参数

print(sum2(10,20,30)) # 三个参数

偏函数

from functools import partial

1. Python 的`functools` 模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。要注意,这里的偏函数和数学意义上的偏函数不一样。

2. 偏函数是用于对函数固定属性的函数,作用就是把一个函数某些参数固定住(也就是设

置默认值),返回一个新的函数,调用这个新的函数会更简单。

# int() base vaild 2-36 => 看源码的注释

print(int("12345")) # 默认int就是10进制

print("转换为7进制:", int("12345", base=7))

# 偏函数就是来设置属性默认值的

from functools import partial

new_int = partial(int, base=2) # 这样就固定了base这个属性值

# 其实和自己写个函数是一致的

def my_int(s, base):

return int(s, base=base)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值