赞
踩
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def函数可以嵌套在另一个def函数之中。调用外层函数时,运行到的内层def语句仅仅是完成对内层函数的定义,而不会去调用内层函数,除非在嵌套函数之后又显式的对其进行调用。
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f = lazy_sum(1, 3, 5, 7, 9)
print(f())
1.这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
2.当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数。
3.打个比方: 一个大盒子,内部有一个小盒子,小盒子里用到一些东西是来自这个大盒子,那么这些来自大盒子的东西,就是闭包。
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print(f1(),f2(),f3())
·
·
·
9 9 9
1.在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。
2.原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9。
3.返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量!
4. fs.append(f) 这里的f是函数,fs是个list,此处并不是对f()进行了调用,输出3个相同引用状态的f()函数f1(), f2(), f3() ,输出3个相同的, 当i=3时刻对应的f()函数值, 即f(3)=9
利用闭包返回一个计数器函数,每次调用它返回递增整数
# -*- coding: utf-8 -*- def createCounter(): #法一 i=0 # 此处i在外函数定义, 因为内函数引用了i, 变量i会保存在内容中 ,不加这一行的话返回结果为1,1,1··· def counter(): nonlocal i # 声明变量i为局部变量 i=i+1 # 声明后变量i可以修改 return i return counter # 测试: counterA = createCounter() print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5 counterB = createCounter() if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]: print('测试通过!') else: print('测试失败!') # -*- coding: utf-8 -*- def createCounter(): # 法二 选择数值可变但是地址不变的变量类型——数组 i = [0] # 初始化数组 def counter(): i[0] += 1 #不修改数组, 只修改数组中元素数值, 数组的地址不变 return i[0] return counter # 测试: counterA = createCounter() print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5 counterB = createCounter() if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]: print('测试通过!') else: print('测试失败!')
关于法二:
在counter函数中,我们并不能改变的i 值,但是如果我们传的i 是一个列表的话,其实本质上传递的是一个地址,在这个地址上我们可以做任意改变.只要这个列表还是这个列表,他的地址就不会变.利用这种特性,我们就可以随便折腾了.
灵活运用lambda表达式
只能有一个表达式,不用写return
装饰器的作用就是可以定义之后,给每个函数都装饰上, 显示程序执行的开始、结束,显示函数执行时间
贴一个up主的讲解,十分清楚。
https://www.bilibili.com/video/BV11s411V7Dt/
step1:在求出素数的同时并给出系统求取素数所需的总时间
可读性低,prime_nums()中既有逻辑又有计时,为了分开这两部分并且规范,所以有了step2
import time def is_prime (num): if num<2: return False elif num ==2: return True else: for i in range (2,num): if num %i==0: return False return True def prime_nums(): t1=time.time() for i in range(2,10000): if is_prime(i): print(i) t2 =time.time() print(t2-t1) prime_nums()
step2
import time def display_time(func): def wrapper(): t1 = time.time() func () t2 = time.time() print(t2 - t1) return wrapper def is_prime (num): if num<2: return False elif num ==2: return True else: for i in range (2,num): if num %i==0: return False return True @display_time def prime_nums(): for i in range(2,10000): if is_prime(i): print(i) prime_nums()
step3:如果prime_nums()函数有返回值时,计算有多少个素数。1229个素数。
import time def display_time(func): def wrapper(): t1 = time.time() result=func () t2 = time.time() print('Total time is:{:.4}s '.format(t2-t1)) return result return wrapper def is_prime (num): if num<2: return False elif num ==2: return True else: for i in range (2,num): if num %i==0: return False return True @display_time def count_prime_nums(): count=0 for i in range(2,10000): if is_prime(i): count =count+1 return count count =count_prime_nums() print(count)
step4:从2到任意数字,求取素数。
import time def display_time(func): def wrapper(*args): t1 = time.time() result=func (*args) t2 = time.time() print("Total time is:{:.4f}s ".format(t2-t1)) return result return wrapper def is_prime (num): if num<2: return False elif num ==2: return True else: for i in range (2,num): if num %i==0: return False return True @display_time def count_prime_nums(maxnum): count=0 for i in range(2,maxnum): if is_prime(i): count =count+1 return count count =count_prime_nums(10000) print(count)
当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
创建自己的模块时,要注意:
1.模块名要遵循Python变量命名规范,不要使用中文、特殊字符;
2.模块名不要和系统模块名冲突,最好先查看系统是否已存在该模块,检查方法是在Python交互环境执行import abc,若成功则说明系统存在此模块。
3.每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。init.py可以是空文件,也可以有Python代码。一个目录+init.py 它就是包;没有__init__.py的就是个普通目录。
if name== ‘main’
如果模块是被导入的,则被导入的模块不直接运行。要进行调用,用 if_name_ == ‘main’ 来规范调用。
当模块直接运行的时候,就执行 if name== ‘main’ 下的代码块 。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。