python语言的高级特性
基于lambda演算的一种编程方式
程序中只有函数
函数可以作为参数,同样可以作为返回值
纯函数式编程语言: LISP, Haskell
Python函数式编程只是借鉴函数式编程的一些特点,可以理解成一半函数式一半Python
高阶函数
返回函数
匿名函数
装饰器
偏函数
lambda表达式
函数: 最大程度复用代码
存在问题: 如果函数很小,很短,则会造成啰嗦
如果函数被调用次数少,则会造成浪费
对于阅读者来说,造成阅读流程的被迫中断
lambda表达式(匿名函数):
一个表达式,函数体相对简单
不是一个代码块,仅仅是一个表达式
可以有参数,有多个参数也可以,用逗号隔开
#“小函数”举例
def printA():
print("AAA")
printA()
lambda表达式的用法
1.以lambda开头
2.后面紧跟着参数,可以有多个,也可以没有
3.参数后面用冒号和表达式隔开
4.没有return
stm = lambda x:100 * x
#调用方式:
print(stm(2))
stm2 = lambda x,y,z:x+100*y-z*5
print(stm2(1,2,3))
高阶函数
#把函数作为参数使用的函数
#变量是可以赋值的
b = 10
a = b
#函数名也是一个变量
def funA():
print("I am funA")
funB = funA
funB()
#由此我们可以看出函数名是一个变量,所以可以作为参数传递
#举例
#正常方式
加粗样式
def A(n):
return n*100
def B(n):
return A(n)*3
print(B(3))
#高阶函数表示
def C(n,f):
return f(n) * 3
print(C(3,A))
#可以随时变更,有很强的的灵活性
####系统给定的高阶函数
#1.map
#原意就是映射,把集合或者列表中的每一个元素,都按一定规则进行操作,生成一个新的列表或者集合
#举例
l1 = [i for i in range(10)]
print(l1)
l2 =[]
for i in l1:
l2.append(i*10)
print(l2)
#利用map操作
def mulTen(n):
return n*10
l3 = map(mulTen,l1)
#print(l3)得到的是一个map类型的,没办法直接print,生成的是一个可迭代的,所以我们可以用for 循环来
for i in l3:
print(i)
#2. reduce
#归并:把一个可迭代的对象归并成一个结果
#对于作为参数的要求:要有两个参数,必须有返回结果
**reduce([1,2,3,4,5]) == f( f(f(f(1,2),3), 4),5)
#reduce 需要导入functools包**
from functools import reduce
def add(x,y):
return x+y
rst = reduce(add,[1,2,3,4,5,6])
print(rst)
filter函数
#对一组函数进行过滤,符合条件的数据会生成一个新的列表,并返回
跟map相比较:
相同:都对列表的每一个元素逐一进行操作
不同:
map会生成一个跟原来数据想对应的新队列
#filter不一定,只要符合条件的才会进入新的数据集合
#filter函数怎么写:
#利用给定函数进行判断
#返回值一定是个布尔值
#调用格式: filter(f, data), f是过滤函数, data是数据
def IsEven(a):
return a%2==0#返回的需要是布尔值
l = [54,54,8,74,1,1,57,1,2,1,785,7,24,574,2,154]
rst = filter(IsEven , l)
print(type(rst))
print(rst)
print([i for i in rst])
#高阶函数—排序
#把一个序列按照给定的算法进行排序
#key: 在排序钱对每一个元素进行key函数运算,可以理解成按照key函数定义的逻辑进行排序
l1 = [54,54,8,74,1,1,57,1,2,1,785,7,24,574,2,154]
l2 = sorted(l1,reverse = False)#从小到大
l3 = sorted(l1,reverse = True)#从大到小
print(l2)
print(l3)
l = [-4,5,-5,6,-7,11,-52,41,-62]
print(sorted(l,key = abs))#abs:按照绝对值的大小进行排列
#字符串也是可以比较的
stru = ["Hahah","xixi","Xinxij","Beibeui","weiwei","nini"]
print(sorted(stru))
print(sorted(stru,key = str.upper))
返回函数
#函数可以返回一个值,也可以返回一个函数做为结果
#普通函数**
def fun():
print("SSS")
return None
a = fun()
print(a)
#函数作为返回值返回,被返回的函数在函数体内定义
def f1():
def f2():
print(" i am in f2")
return 2
return f2
f3 = f1()
#此时f3就相当于f2
f3()
print(f3())
def f4( *args):
def f5():
rst = 0
for i in args:
rst+= i
return rst
return f5
c= f4(0,1,2,3,4,6,7,8)
c()
print(c)
print(c())
闭包
#当一个函数在内部定义函数,并且内部的函数应用外部函数的参数或者局部变量,
#当内部函数被当做返回值的时候,相关参数和变量保存在返回的函数中,这种结果,叫闭包
#上面定义的myF4是一个标准闭包结构
#闭包常见坑
def count():
# 定义列表,列表里存放的是定义的函数
fs = []
for i in range(1,4):
# 定义了一个函数f
# f是一个闭包结构
def f():
return i*i
fs.append(f)
return fs
f1,f2,f3 = count()
print(f1())
print(f2())
print(f3())
#我们期望的是输出1 4 9
#而输出的是 9 9 9
出现的问题:
#造成上述状况的原因是,返回函数引用了变量i, i并非立即执行,而是等到三个函数都返回的时候才统一使用,
#此时i已经变成了3,最终调用的时候,都返回的是 3*3
#此问题描述成:返回闭包时,返回函数不能引用任何循环变量
#解决方案: 再创建一个函数,用该函数的参数绑定循环变量的当前值,
无论该循环变量以后如何改变,已经绑定的函数参数值不再改变
#修改上述函数
def count2():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3 = count2()
print(f1())
print(f2())
print(f3())
#装饰器
def hello():
print("Hello world!")
hello()
f= hello
f()
#f和hello是一个函数
print(id(f))
print(id(hello))
print(f.__name__)
print(hello.__name__)
现在由新的需求:
对hello功能进行扩展,每次打印hello之前打印当前系统时间
而实现这个功能又不能改动现有代码
==>使用装饰器
装饰器(Decrator)
在不改动函数代码的基础上无限制扩展函数功能的一种机制,本质上讲,装饰器是一个返回函数的高阶函数
#装饰器的使用: 使用@语法, 即在每次要扩展到函数定义前使用@+函数名
import time
#装饰器需要是高阶函数
def printTime(f):
def wrapper(*args, **kwargs):
print("Time: ", time.ctime())
return f(*args, **kwargs)
return wrapper
@printTime
def hello():
print("Hello world")
hello()
#手动执行装饰器
def hello1():
print("我是手动执行的")
h = printTime(hello1)
h()
#h = printTime的返回值就是其中的wrapper函数
#h():就是调用wrapper函数,其中有一个打印时间的函数,之后返回了一个f函数,而f函数就是hello1,执行一行文字的打印
偏函数
#参数固定的函数,相当于一个由特定参数的函数体
functools.partial的作用是,把一个函数某些函数固定,返回一个新函数
#将十进制转换成8进制
print(int("12345",base = 8))
#函数的书写
def int16(x,base = 16):
return int(x,base)
print(int16("12345"))
#偏函数
import functools
#实现上面int16的功能
int16 = functools.partial(int, base=16)
int16("12345")