闭包函数
函数传参的方式一
def inner(x):
print(x)
inner(1) # 1
函数的传参方式二 (闭包函数,把变量和函数一起包起来,下次要用直接调用)
def outter(x):
def inner():
print(x)
return inner
inner = outter(2)
inner() # 2
def get_res(url):
res = requests.get(url)
print(res.text)
get_res('https://www.taobao.com')
def func(url):
def get_res():
res = requests.get(url)
print(res.text)
return get_res
baidu_spider = func('https://www.baidu.com')
baidu_spider()
装饰器
装饰的工具(函数),这个函数有装饰的作用装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B,
装饰器要满足两个条件:
1. 不改变函数B的调用方式
2. 不改变函数B的源码
def A():
"""装饰器"""
pass
def B():
"""被装饰的对象"""
pass
B()
def index():
"""被装饰的函数"""
print('hello, index')
index()
1. 打印函数运行的时间
1.1 改变了函数体代码,没改变调用方式
import time
def index():
start = time.time()
print('hello, index')
time.sleep(1)
end = time.time()
print(end - start)
index()
1.1 # 没改变调用方式,也没改变源码,但是不通用
import time
def index():
"""被装饰的函数"""
print('hello, index')
start = time.time()
index()
time.sleep(1)
end = time.time()
print(end-start)
1.2没改变源码,也没改变调用方式
import time
def deco(func): # func = index
"""装饰器函数"""
def inner():
start = time.time()
func() # index
time.sleep(1)
end = time.time()
print(end - start)
return inner
def index():
"""被装饰的函数"""
print('hello, index')
index = deco(index) # index = inner
index()
2.检测index的运行的时间,但是不能改变index的调用方式,以及index的源码
# 写一个装饰器
def deco(func): # func = 真正的index
"""装饰器"""
def f1(): # 重新创建的index
start = time.time()
func() # 真正的index()
end = time.time()
print(end-start)
return f1
index(重新创建的index) = deco(index(真正的index)) # index = f1
index()
import time
def deco(func):
def f1(*args, **kwargs):
print('args:',args) # (10,) 元组只有一个元素时,必须要加逗号
print('kwargs:',kwargs)
start = time.time()
res = func(*args, **kwargs) # 真正的index()
end = time.time()
print(end - start)
return res
return f1
@deco # 语法糖(更精简的代码) index = deco(index)
def index(x, a=1):
print('x', x)
print('a', a)
print('hello index')
time.sleep(1)
return 123
index = deco(index) # index = f1
index(10) # f1(1)
装饰器模板
def login(func):
def inner(*args, **kwargs):
# 登录功能
username = input('usrename:')
pwd = input('pwd:')
if username == 'nick' and pwd == '123':
print('登录成功')
res = func(*args, **kwargs) # shopping()
return res
else:
print('登录失败')
return inner
def time_count(func):
def inner(*args,**kwargs):
start = time.time()
res = func(*args,**kwargs)
end = time.time()
print(end-start)
return res
return inner
def outter(func):
def inner(*args,**kwargs):
# 加功能
func(*args,**kwargs)
return inner
先执行离得近的语法糖,在执行远的语法糖
@time_count
@login
@outter
def shopping():
print('shopping')
shopping()
三层装饰器: 给双层装饰器加参数
判断账号密码来自于哪个地方
def auth(engine):
def login(func):
def inner(*args, **kwargs):
# 登录功能
if engine == 'file':
username = input('usrename:')
pwd = input('pwd:')
if username == 'nick' and pwd == '123':
print('登录成功')
func(*args, **kwargs) # shopping()
else:
print('登录失败')
elif engine == 'db':
print('账号密码来自于数据库,非法请求')
return inner
return login
@auth('db')
def shopping():
print('shopping')
login = auth('db') # login = login
shopping = login(shopping) # shopping = inner
shopping() # inner()
装饰器模版
# 双层装饰器
def outter(func):
def wrapper(*args, **kwargs): # wrapper是未来要运行的函数
# 加功能
func(*args, **kwargs) # func是被装饰的函数
return wrapper
@outter
def shopping():
print('shopping')
# 三层装饰器:给双层装饰器加参数的
def sanceng(engine):
def outter(func):
def wrapper(*args, **kwargs): # wrapper是未来要运行的函数
# 加功能
print(engine)
func(*args, **kwargs) # func是被装饰的函数
return wrapper
return outter
迭代器对象
更新换代, 重复, 基于上一次的结果推出下一次的结果
1)可迭代(具有__iter__方法) 对象
x = 1 # 不可迭代对象
s = 'nick' # 可迭代对象
s.__iter__()
lt = [1, 2, 3] # 可迭代对象
dic = {'a': 1, 'b': 2} # 可迭代对象
tup = (1,) # 元组只有一个元素必须得加逗号# 可迭代对象
se = {1, 2, 3} # 可迭代对象
f = open('time.py') # 可迭代对象
def func(): # 不可迭代对象
pass
有__iter__()方法的对象就是可迭代对象,然后出了数字类型和函数之外都是可迭代对象
s = 'nick'
s_iter = s.__iter__()
print(s_iter.__next__()) # 基于索引(基于上一次结果)通过__next__进行迭代
s = 'nick'
s[0]
dic = {'a':1,'b':2} # 可迭代对象
dic['a']
dic_iter = dic.__iter__() # 不依赖索引取值 # 迭代器对象
print(dic_iter.__next__())
2)迭代器对象: 具有__iter__以及__next__方法的叫做迭代器对象
s = 'nick' # 可迭代对象,不属于迭代器对象
s.__iter__()
lt = [1, 2, 3] # 可迭代对象,不属于迭代器对象
dic = {'a': 1, 'b': 2} # 可迭代对象,不属于迭代器对象
tup = (1,) # 元组只有一个元素必须得加逗号# 可迭代对象,不属于迭代器对象
se = {1, 2, 3} # 可迭代对象,不属于迭代器对象
f = open('time.py') # 可迭代对象,迭代器对象
#只有文件是迭代器对象
3)for循环原理 # 迭代循环
lt = [1,2,3]
lt_iter = lt.__iter__()
while 1:
try:
print(lt_iter.__next__())
except StopIteration:
break
for i in lt: # 可迭代对象;迭代器对象 # 不依赖索引取值,而是迭代取值
print(i)
1. 首先使用iter把lt变成迭代器对象;对于文件也要使用iter方法吧文件再一次iter下
2. 然后使用next方法进行迭代取值
3. 判断StopIteration异常,遇到异常终止
f = open('time.py') # 可迭代对象,迭代器对象
f_iter = f.__iter__()
print(id(f_iter))
f_iter_iter = f_iter.__iter__()
print(id(f_iter_iter))
可迭代对象: 具有__iter__方法的对象就是可迭代对象,除了数字类型和函数都是可迭代对象
迭代器对象: 具有__iter__和__next__方法的都是迭代器对象,只有文件
迭代器对象一定是可迭代对象; 可迭代对象不一定是迭代器对象
for循环 == 迭代循环
dic ={'a':1,'b':2}
for i in dic:
print(i)
1. 把lt(可迭代对象/迭代器对象)用__iter__方法转换成迭代器对象
2. 使用__next__取出迭代器里的所有值
3. 使用__next__方法取尽迭代器中的所有值,一定会报错,通过异常捕捉退出while循环
# 解决了不依赖索引取值
也可以使用iter(),next()
dic ={'a':1,'b':2}
dic_iter = iter(dic)
print(next(dic_iter))
print(next(dic_iter))