Python基础第五天
如果在一个内部函数里,对在外作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包。
def f():
x = 10
def g():
print(x)
return g
f()() # 10(f()相当于g f()()相当于g())
h = f()
h() # 10
闭包=内部函数g()+定义函数时的环境(x)
def f(x):
def g():
print(x)
return g
h = f(1)
h()
也是闭包函数
import time #使用time模块需要导包(调用方式:time.time)
def foo():
start = time.time()# 是一个时间戳,表示从1970年1月1日00:00:00至现在的总秒数。
print("foo...")
time.sleep(1)# 添加休眠1秒,否则程序进行太快,看不出来运行时间。
end = time.time()
print(f"运行了{end-start}秒")
foo() #在后面一定要调用否则运行不出来
在不修改源代码的基础上给函数增加新的功能:
def foo(): #原函数
print("foo...")
time.sleep(1)
def show_time(func): # 该函数用来展示时间
def inner():
start = time.time()
func()
end = time.time()
print(f"运行了{end-start}秒")
return inner
foo = show_time(foo) # 这里类似闭包
foo() # 增加计算运行时间功能
也可以这样写:
import time # 一定要写的
def show_time(func): # 该函数用来展示时间
def inner():
start = time.time()
func()
end = time.time()
print(f"运行了{end-start}秒")
return inner
@ show_time# 等价于foo = show_time(foo)
def foo():
print("foo...")
time.sleep(1)
@ show_time# 等价于too = show_time(too)
def too():
print("too...")
time.sleep(2)
foo()
too()
import time
def show_time(func): # 该函数用来展示时间
def inner(a, b):
start = time.time()
func(a, b)
end = time.time()
print(f"运行了{end-start}秒")
return inner
@ show_time# 等价于add = show_time(add)
def add(a, b):
print(a+b)
time.sleep(1)
add(1,2)
关于*args **kwargs:
import time
def show_time(func): # 该函数用来展示时间
def inner(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time()
print(f"运行了{end-start}秒")
return inner
@ show_time # 等价于add = show_time(add)
def add(*args, **kwargs):
sum = 0
for i in args:
sum += i
print(sum)
time.sleep(1)
add(1,2,3,4)
总结:
闭包:就是能够读取其他函数内部变量的函数
python闭包的作用:保存外部函数的变量,不会随着外部函数调用完而销毁
python闭包的条件:
装饰器:实际上也是一个闭包函数,也是一个函数嵌套。
装饰器的作用:在不改变原函数的情况下,对已有的函数进行额外的功能扩展
装饰器的形成条件:
区别:装饰器实质上是一个闭包函数,但是装饰器这个闭包函数的参数有且只有一个,并且是函数类型的。否则它就是闭包函数。
知识点回顾:
列表生成式:[x for x in range(10)]
是一个可迭代对象
next()
用来调用值
g = (x for x in range(10))
print(next(g)) # 0 (获取g的第一个值)
print(next(g)) # 1 (获取g的第二个值)
print(next(g)) # 2 (获取g的第三个值)
# 不可以指定获取值,也不可以获取的超过此范围,否则报错。
for循环的本质就是调用next
r = (x for x in range(1,6))
for i in r:
print(i)
创建生成器:
def f():
print("11")
yield 1
h = f() # 表示一个生成器函数
print(next(h))
# yield相当于挂起,存档的意思
def a():
print("a")
yield 1
print("aa")
yield 2
for i in a():
print(i)
# a
# 1
# aa
# 2
什么是可迭代对象?
如:
l = [1, 2, 3]
l.__iter__()
t = (1, 2, 3)
t.__iter__()
d = {'name':'XX'}
d.__iter__()
生成器就是迭代器
l = [1, 2, 3]
d = iter(l)
print(next(d)) # 1
print(next(d)) # 2
print(next(d)) # 3
for循环内部的本质
for i in [1, 2, 3]:
print(i)
[1, 2, 3].__iter__()
# 1
# 2
# 3
die = iter([1, 2, 3])
while True:
try:
print(next(die))
except StopIteration:
break# 否则会报错(超过此范围)
迭代器的优点:
一个函数的内部调用了自己
def func():
print("222")
func()
func()
# 会一直打印222,最后报错
递归的原则:如果要定义一个递归函数,不想让它报错,就要设计一个出口并不断向出口接近
打印1-50
def func(x):
if x == 51:
return # 结束当前函数
print(x)
return func(x+1)
func(1)
求9的阶乘
def f(n):
if n == 1:
return True
return n*f(n-1)
a = f(9)
print(a) # 362880
函数的递归:
是函数嵌套调用的一种特殊形式。函数嵌套调用一个函数的过程中调用了另外的函数,函数的递归在调用一个函数的过程中又调用回到本身。
定义:包含一系列数据、函数、类的文件,通常以.py结尾
第一种:import 模块名 # 将某个模块的整体导入到当前模块中
第二种:from 模块名 import 成员名 # 将指定成员导入到当前模块中
第三种:from 模块名 import * # 将指定模块的所有成员导入到当前模块中
注意:导入进来的成员不要与当前模块成员名称相同。如果相同,按就近原则。(程序是从上往下进行的)
名字太长或有重复的可以取别名(as)
__file__: 模块对应的文件路径名
文件绝对路径:从操作系统的根开始的
__name__: 模块自身的名字,可以判断是否为主模块
主模块:__main__
非主模块:真名
python的__main__的作用:
把一些非必要的代码放到main函数里面
main的标准语法:
if __name__ == '__main__':
print('main在哪里哪里就是主程序')
1.内置模块
在内部就可以直接使用的,如print、input
2.标准库模块
安装python的时候就已经安装可以使用的,用import导入即可,如,time、random
3.pip模块
通常是开源的,需要自己安装。
通过pip install 模块名
卸载pip: pip install 模块名
查询所有安装的第三方模块:pip list
4.用户自己编写的模块
语句 --> 函数 --> 类 --> 模块 --> 包
包的定义:将模块以文件夹的形式进行分组管理,也就是管理模块的。
作用:让一些相关的模块组织在一起,使结构更加清晰。
from 包.模块 import 成员
import 模块名 as 新模块名
是包内必须存在的文件,会在包加载的时候被自动调用。
在导入这个包里面的模块的时候,__init__.py的代码也会自动执行,所以可以利用这个机制,在__init__.py里面写上关于这个包内模块的说明
调用:显示:__init__内部:包内文件hello内部:
https://docs.python.org/3/py-modindex.html
可以由这个网站找到python的标准库(可以直接使用的)