高阶函数
- 接收函数作为参数
- 或者将函数作为返回值返回的函数就是高阶函数
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def fn1(i):
if i % 2 == 0:
return True
def fn(fun, list1):
new_list = []
for i in list1:
if fun(i):
new_list.append(i)
return new_list
r = fn(fn1, list1)
print(r)
结果:
[2, 4, 6, 8, 10]
匿名函数
- filter
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
def is_odd(n):
return n % 2 == 1
newlist = list(filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
print(newlist)
结果:
[1, 3, 5, 7, 9]
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import math
def is_sqr(x):
return math.sqrt(x) % 1 == 0
newlist = list(filter(is_sqr, range(1, 101)))
结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
- lambda
使用lambda来创建匿名函数。
print((lambda a,b:a+b)(1,2))
结果:
3
MAXIMUM = lambda x, y: (x > y) * x + (x < y) * y
MINIMUM = lambda x, y: (x > y) * y + (x < y) * x
if __name__ == '__main__':
a = 10
b = 20
print('The largar one is %d' % MAXIMUM(a, b))
print('The lower one is %d' % MINIMUM(a, b))
闭包
闭包的作用:
闭包可以保存外部函数的变量,不会随着外部函数调用完而销毁
注意点:
由于闭包引用了外部函数的变量(参数), 则外部函数的变量没有及时释放,消耗内存
• 闭包的好处
• 通过闭包可以创建一些只有当前函数能访问的变量
• 可以将一些私有数据藏到闭包中
• 行成闭包的条件
• 函数嵌套
• 将内部函数作为返回值返回
• 内部函数必须要使用到外部函数的变量
def fun_out(num1):
def fun_inner(num2):
r = num1 + num2
print(r)
return fun_inner
r = fun_out(1)
r(3)
r(3)
r(3)
r(3)
r(3)
r(3)
结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python37\python.exe D:/python/day09.py
4
4
4
4
4
4
Process finished with exit code 0
def fun_out(num1):
def fun_inner(num2):
num1 = 10
r = num1 + num2
print(r)
return fun_inner
r = fun_out(1)
r(2)
结果:
12
生成器
- 迭代器
迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
字符串,列表或元组对象都可用于创建迭代器:
- 创建一个迭代器
把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。
如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 init(), 它会在对象初始化的时候执行。
iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
next() 方法(Python 2 里是 next())会返回下一个迭代器对象。
创建一个返回数字的迭代器,初始值为 1,逐步递增 1:
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
结果:
1
2
3
4
5
- 生成器
生成器的特性: 生成器相当于一个容器, 当你把容器里的数据全部取出来之后,那么容器里面就不在有数据了
生成器只能取一次,用完了之后就没有了,需要你自己在重新生成一次才可以
第二种方式: 用函数的方式 yield
当使用yield关键字之后,函数不再是函数,而是一个生成器
当程序执行到yield的时候,程序就会停止 和 input类似
生成器,会记住你之前取到的元素的位置,下一次继续去数据的时候,他会在那个位置继续往下取数据
在 Python 中,使用了 yield 的函数被称为生成器(generator)。 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 在调用生成器运行的过程中,每次遇到
yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
def fn():
print('fn执行了')
i = 1
while True:
yield i
i += 1
r = fn()
# print(r)
print(next(r))
print(next(r))
print(next(r))
print(next(r))
结果:
C:\Users\Administrator\AppData\Local\Programs\Python\Python37\python.exe D:/python/day09.py
fn执行了
1
2
3
4
Process finished with exit code 0
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
print(f)
while True:
try:
print(next(f), end=" ")
except:
pass
结果:
<generator object fibonacci at 0x0000000001E07750>
0 1 1 2 3 5 8 13 21 34 55
推导式
类表推导式
旧的类表 ----> 新的列表
语法: [表达式 for 变量 in 旧列表 if 条件]
list1 = ['cheney', 'jerry', 'amy', '居然', 'tony', 'anny', 'james', '豆腐', 'wolf']
def fn():
pass
result = [name for name in list1 if len(name) > 4]
print(result)
装饰器
为什么要这样
要想理解装饰器为什么要有这种结构,要首先想明白装饰器的目标是什么。
它的价值在于为原函数f增加一些行为,前提必须不能破坏函数f,所以肯定不能改变f的内部结构,所以只能在调用f前后定义一些行为。
同时,装饰器函数decorator返回值又是什么?你可以思考下,返回一个函数是再好不过的了,它包装了原函数f.
• 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
• 如果修改的函数多,修改起来会比较麻烦
• 不方便后期的维护
• 这样做会违反开闭原则(ocp)
• 程序的设计,要求开发对程序的扩展,要关闭对程序的修改
- 装饰一个函数
def decorator(f):
# 定义要返回的函数
def g():
print('函数f执行前的动作')
f()
print('函数f执行后的动作')
return g
def printStar(f):
def g():
print('*'*20)
f()
print('*'*20)
return g
@printStar
def f():
print('hello world')
if __name__ == '__main__':
f()
结果:
********************
hello world
********************
- 装饰一个类
def decorator(cls):
# 定义要返回的函数
def g():
print('类cls执行前的动作')
f()
print('类cls执行后的动作')
return g
@+自定义装饰器 装饰要想装饰的函数。
def decorator(f):
# 定义要返回的函数
def g():
print('函数f执行前的动作')
f()
print('函数f执行后的动作')
return g
@decorator
def f():
print('hello word')
f()
结果:
函数f执行前的动作
hello word
函数f执行后的动作
def add(a, b):
return a + b
def fn1():
print('我是fn1')
def fn(a, b):
print('函数开始执行')
r = add(a, b)
print('函数执行结束')
return r
r = fn(1, 2)
print(r)
结果:
函数开始执行
函数执行结束
3
- 装饰器层叠
def printStar(f):
def g():
print('*'*20)
f()
print('*'*20)
return g
def printLine(f):
def g():
print('-'*20)
f()
print('-'*20)
return g
@printStar
@printLine
def f():
print('hello world')
if __name__ == '__main__':
f()
结果:
********************
--------------------
hello world
--------------------
********************
作业
1.请使用装饰器实现已存在的函数的执行所花费的时间。
import time
def run_time(fn):
def wrapper(*args, **kw):
start = time.time()
res = fn()
print('%s 运行了 %f 秒' % (fn.__name__, time.time() - start))
return res
return wrapper
@run_time
def fn():
a = input("请输入4位整数作为年份:")
a = eval(a)
if a % 400 == 0 or (a % 4 == 0 and not a % 100 == 0):
print("{}是闰年".format(a))
else:
print("{}不是闰年".format(a))
fn()
结果:
C:\Users\giser\AppData\Local\Programs\Python\Python37\python.exe D:/pycharm/pythonbasic/day09.py
请输入4位整数作为年份:2020
2020是闰年
fn 运行了 2.180000 秒
Process finished with exit code 0