文章目录
正文:
1 生成器
1)生成器:
-
生成器定义
- 生成器与迭代器可以看成是一种。生成器的本质就是迭代器
- 唯一区别:生成器是我们自己用python代码构建的数据结构。迭代器都是提供的,或者转化得来的。
-
获取生成器的三种方式:
- 生成器函数
- 生成器表达式
- python内部提供的一些生成器
-
生成器函数获取生成器:
# 函数 def func1(): print(111) print(222) return 3 ret = func1() print(ret) # # 生成器函数 def func2(): print(111) print(222) yield 3 a = 1 b = 2 c = a + b print(c) yield 4 ret = func2() # print(ret) print(next(ret)) print(next(ret)) print(next(ret)) # 一个next 对应一个yield ''' return and yield ''' # return ;函数中只存在一个return结束函数,并且给函数的执行者返回值。 # yield:只要函数中有yield那么它就是生成器函数而不是函数了。 # 生成器函数中可以存在多个yield,yield不会结束生成器函数,一个yield对应一个next。 # 吃包子问题解析生成器 def func11(): l1 = [] for i in range(1,5001): l1.append(f'{i}号包子') return l1 ret = func11() print(ret) def gen_func22(): for i in range(1,5001): yield f'{i}号包子' ret = gen_func() for i in range(200): print(next(ret)) for i in range(200): print(next(ret)) ''' yield from ''' def func111(): l1 = [1, 2, 3, 4, 5] yield l1 ret = func111() print(next(ret)) def func222(): l1 = [1, 2, 3, 4, 5] yield from l1 ''' yield 1 yield 2 yield 3 yield 4 yield 5 ''' # 将l1这个列表变成了迭代器返回。 ret = func222() print(next(ret)) print(next(ret)) print(next(ret)) print(next(ret)) print(next(ret)) # 多个yield def func(): lst1 = ['卫龙', '老冰棍', '北冰洋', '牛羊配'] lst2 = ['馒头', '花卷', '豆包', '大饼'] yield from lst1 yield from lst2 g = func() for i in range(8): print(next(g))
2 生成器表达式、列表推导式
1)列表推导式
- 基本结构
l1 = [i for i in range(1,11)]
l2 = [i if i>5 else 0 for i in range(10)]
- 列表推导式优缺点:
- 缺点
- 列表推导式只能构建比较复杂并且有规律的列表。
- 超过三层循环才能构建成功的,就不建议用列表推导式。
- 查找错误(debug模式)不行。
- 优点
- 一行构建,简单。
- 缺点
2)生成器表达式
-
与列表推导式写法几乎相同:(i for i in range(10))
-
列表推导式和生成器表达式区别:
- 写法:[] ()
- iterable可迭代对象 和 iterator 迭代器的区别
-
字典推导式:
lst1 = ['jay', 'jj', 'meet'] lst2 = ['周杰伦','林俊杰','元宝'] dic = { lst2[i]: lst1[i] for i in range(len(lst1))} print(dic)
-
集合推导式:
print({i for i in range(1,11)})
3 内置函数
python提供了68个内置函数
1)比较重要
all() # 可迭代对象中,全都是True才是True
any() # 可迭代对象中,一个是True就是True
bytes() # 将数转换为二进制数
callable() # 判断该对象是否可调用(如字符串不可被调用,函数可被调用,func())
complex(实, 虚) # 复数,实+虚j
eval() # i)将字符串表达式作为代码执行。ii)将数据字符串转换为数据原本的数据类型。iii)一次input赋值给多个变量 a, b = eval(input())
exec() # 与eval()基本相同,可以对代码块字符串进行相关操作
format()
frozenset() # 不可变集合(不能添加和删除)
globals() # 所有全局变量
hash() # 获取哈希值
help() # 查看帮助
id() # 获取内存地址
input()
int()
iter() # 生成迭代器
locals() # 获取全部局部变量(字典)
next() # 返回迭代器的下一个项目
bin() # 将十进制转换位二进制并返回
oct() # 将十进制转换位八进制并返回
hex() # 将十进制转换为十六进制并返回
ord() # 输入字符找字符编码位置
chr() # 输入位置数字找对应字符
pow(x, y) # 求x**y次幂,三个参数时为x**y % 第三个参数
divmod(除数, 被除数) # divmod() 函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。
round(小数, 位数) # 保留浮点数的小数位数
repr() # 返回一个对象的 string 格式。
2)非常重要
abs() # 绝对值
enumerate() # enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
filter() # 列表推导式的筛选模式,列表推导式返回列表,filter()返回迭代器
"""
filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
"""
l1 = [2, 3, 4, 1, 6, 7, 8]
print([i for i in l1 if i > 3]) # 返回的是列表
ret = filter(lambda x: x > 3,l1) # 返回的是迭代器
map() # 列表推导式的循环模式,列表推导式返回列表,map()返回迭代器
"""
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
"""
l1 = [1, 4, 9, 16, 25]
print([i**2 for i in range(1,6)]) # 返回的是列表
ret = map(lambda x: x**2,range(1,6)) # 返回的是迭代器
max() # max(*args, key=None),key是函数名,表示对可迭代对象进行key函数操作后进行max操作
min() # 比较键值对时默认按照键比较,可加key函数名
open()
range()
print() # print(self, *args, sep=’ ‘, end=’\n’, file=None)
len()
list()
dict()
str()
float()
reversed() # 对列表进行翻转获取一个迭代器,list.reverse()方法对原列表进行翻转
set()
sorted() # 对列表进行排序并生成新列表,list.sort()方法对原列表进行排序,也有key参数,还有reverse参数设置反转排序
sum()
tuple()
type()
zip() # 用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
dir() # 不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
reduce() # 已经不是一个内置函数,转化为python3中是一个模块的方法
from functools import reduce
def func(x,y):
'''
第一次:x y : 11 2 x + y = 记录: 13
第二次:x = 13 y = 3 x + y = 记录: 16
第三次 x = 16 y = 4 .......
'''
return x + y
l = reduce(func,[11,2,3,4])
print(l)
3)挺重要
classmethod() # 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。
delattr() # 删除属性。delattr(x, ‘foobar’) 相等于 del x.foobar。
getattr() # 用于返回一个对象属性值。
hasattr() # 用于判断对象是否包含对应的属性。
issubclass()
isinstance() # isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。type() 不会认为子类是一种父类类型,不考虑继承关系。isinstance() 会认为子类是一种父类类型,考虑继承关系。
object()
property() # 在新式类中返回属性值。
setattr()
staticmethod() # 返回函数的静态方法。可以实现实例化使用 C().f(),当然也可以不实例化调用该方法 C.f()
super()
4 匿名函数
一句话函数,比较简单的函数。lambda funcname: function
5 闭包
1)定义
内层函数对外层函数非全局变量的引用,就会形成闭包。
'''
eg:例如:整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,
然后计算他的平均值:平均值要考虑直至目前为止所有的价格。
比如大众推出了一款新车:小白轿车。
第一天价格为:100000元,平均收盘价:100000元
第二天价格为:110000元,平均收盘价:(100000 + 110000)/2 元
第三天价格为:120000元,平均收盘价:(100000 + 110000 + 120000)/3 元
'''
# 方案一:
# l1 = [] # 全局变量 数据不安全
# def make_averager(new_value):
# l1.append(new_value)
# total = sum(l1)
# averager = total/len(l1)
# return averager
# print(make_averager(100000))
# 方案二: 数据安全,l1不能是全局变量。
# 每次执行的时候,l1列表都会重新赋值成[]
# li = []
# def make_averager(new_value):
# l1 = []
# l1.append(new_value)
# total = sum(l1)
# averager = total/len(l1)
# return averager
# print(make_averager(100000))
# print(make_averager(110000))
# 方案三: 闭包
def make_averager():
l1 = []
def averager(new_value):
l1.append(new_value)
print(l1)
total = sum(l1)
return total/len(l1)
return averager
avg = make_averager() # averager
print(avg(100000))
print(avg(110000))
2)特点
- 被引用的非全局变量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系,自由变量不会在内存中消失
- 闭包现象只能存在与嵌套函数中。
3)作用
保证数据的安全。
4)判断
# 如何判断一个嵌套函数是不是闭包
# 1,闭包只能存在嵌套函数中。
# 2, 内层函数对外层函数非全局变量的引用(使用),就会形成闭包。
# 例一:
# def wrapper():
# a = 1
# def inner():
# print(a)
# return inner
# ret = wrapper()
# 闭包
#
# # 例二:不是闭包
# a = 2
# def wrapper():
# def inner():
# print(a)
# return inner
# ret = wrapper()
# # 例三:
# 也是闭包!
# def wrapper(a,b):
# def inner():
# print(a)
# print(b)
# return inner
# a = 2
# b = 3
# ret = wrapper(a,b)
# 如何代码判断闭包?
# print(ret.__code__.co_freevars) # ('a', 'b')
6 装饰器
1)开放封闭原则
- 开放:对代码的拓展是开放的。
- 封闭:对源码的修改是封闭的。
2)装饰器定义
-
完全遵循开放封闭原则。
-
在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。
-
# 装饰器:装饰,装修,房子就可以住,如果装修,不影响你住,而且体验更加,让你生活中增加了很多功能:洗澡,看电视,沙发。 # 器:工具。 # 开放封闭原则: # 开放:对代码的拓展开放的, 更新地图,加新枪,等等。 # 封闭:对源码的修改是封闭的。闪躲用q。就是一个功能,一个函数。 别人赤手空拳打你,用机枪扫你,扔雷.....这个功能不会改变。 # 装饰器:完全遵循开放封闭原则。 # 装饰器: 在不改变原函数的代码以及调用方式的前提下,为其增加新的功能。 # 装饰器就是一个函数。 # 版本一: 大壮 写一些代码测试一下index函数的执行效率。 import time # def index(): # '''有很多代码.....''' # time.sleep(2) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # # def dariy(): # '''有很多代码.....''' # time.sleep(3) # 模拟的网络延迟或者代码效率 # print('欢迎登录日记页面') # print(time.time()) # 格林威治时间。 # print(111) # time.sleep(3) # print(222) # 版本一有问题: 如果测试别人的代码,必须重新赋值粘贴。 # start_time = time.time() # index() # end_time = time.time() # print(end_time-start_time) # # start_time = time.time() # dariy() # end_time = time.time() # print(end_time-start_time) # # 版本二:利用函数,解决代码重复使用的问题 # import time # def index(): # '''有很多代码.....''' # time.sleep(2) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # # index() # def dariy(): # '''有很多代码.....''' # time.sleep(3) # 模拟的网络延迟或者代码效率 # print('欢迎登录日记页面') # # def timmer(f): # f= index # start_time = time.time() # f() # index() # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # timmer(index) # 版本二还是有问题: 原来index函数源码没有变化,给原函数添加了一个新的功能测试原函数的执行效率的功能。 # 满足开放封闭原则么?原函数的调用方式改变了。 # 版本三:不能改变原函数的调用方式。 # import time # def index(): # '''有很多代码.....''' # time.sleep(2) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # # def timmer(f): # f = index (funciton index123) # def inner(): # inner :(funciton inner123) # start_time = time.time() # f() # index() (funciton index123) # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # return inner # (funciton inner123) # timmer(index) # index() # ret = timmer(index) # inner # ret() # inner() # index = timmer(index) # inner (funciton inner123) # index() # inner() # def func(): # print('in func') # # def func1(): # print('in func1') # # # func() # # func1() # func() # func = 666 # func(0) # 版本四:具体研究: # import time # def index(): # '''有很多代码.....''' # time.sleep(2) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # # def timmer(f): # f = index # # f = <function index at 0x0000023BA3E8A268> # def inner(): # start_time = time.time() # f() # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # return inner # # index = timmer(index) # index() # 版本五:python做了一个优化;提出了一个语法糖的概念。 标准版的装饰器 # import time # # timmer装饰器 # def timmer(f): # def inner(): # start_time = time.time() # f() # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # return inner # # # @timmer # index = timmer(index) # def index(): # '''有很多代码.....''' # time.sleep(0.6) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # return 666 # ret = index() # print(ret) # def dariy(): # '''有很多代码.....''' # time.sleep(3) # 模拟的网络延迟或者代码效率 # print('欢迎登录日记页面') # dariy() # # index = timmer(index) # # index() # # dariy = timmer(dariy) @timmer # dariy() # # 版本六: 被装饰函数带返回值 # # import time # # timmer装饰器 # def timmer(f): # # f = index # def inner(): # start_time = time.time() # # print(f'这是个f():{f()}!!!') # index() # r = f() # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # return r # return inner # # @timmer # index = timmer(index) # def index(): # '''有很多代码.....''' # time.sleep(0.6) # 模拟的网络延迟或者代码效率 # print('欢迎登录博客园首页') # return 666 # # 加上装饰器不应该改变原函数的返回值,所以666 应该返回给我下面的ret, # # 但是下面的这个ret实际接收的是inner函数的返回值,而666返回给的是装饰器里面的 # # f() 也就是 r,我们现在要解决的问题就是将r给inner的返回值。 # ret = index() # inner() # print(ret) # 版本八: 被装饰函数带返回值 import time # timmer装饰器 # def timmer(f): # # f = index # def inner(*args,**kwargs): # # 函数的定义:* 聚合 args = ('李舒淇',18) # start_time = time.time() # # print(f'这是个f():{f()}!!!') # index() # r = f(*args,**kwargs) # # 函数的执行:* 打散:f(*args) --> f(*('李舒淇',18)) --> f('李舒淇',18) # end_time = time.time() # print(f'测试本函数的执行效率{end_time-start_time}') # return r # return inner # # @timmer # index = timmer(index) # def index(name): # '''有很多代码.....''' # time.sleep(0.6) # 模拟的网络延迟或者代码效率 # print(f'欢迎{name}登录博客园首页') # return 666 # index('纳钦') # inner('纳钦') # @timmer # def dariy(name,age): # '''有很多代码.....''' # time.sleep(0.5) # 模拟的网络延迟或者代码效率 # print(f'欢迎{age}岁{name}登录日记页面') # dariy('李舒淇',18) # inner('李舒淇',18) # 标准版的装饰器; # def wrapper(f): # def inner(*args,**kwargs): # '''添加额外的功能:执行被装饰函数之前的操作''' # ret = f(*args,**kwargs) # '''添加额外的功能:执行被装饰函数之后的操作''' # return ret # return inner
3)装饰器的应用
# 装饰器的应用:登录认证
def login():
pass
def register():
pass
status_dict = {
'username': None,
'status': False,
}
def auth(f):
'''
你的装饰器完成:访问被装饰函数之前,写一个三次登录认证的功能。
登录成功:让其访问被装饰得函数,登录没有成功,不让访问。
:param f:
:return:
'''
def inner(*args,**kwargs):
'''访问函数之前的操作,功能'''
if status_dict['status']:
ret = f(*args,**kwargs)
'''访问函数之后的操作,功能'''
return ret
else:
username = input('请输入用户名').strip()
password = input('请输入密码').strip()
if username == 'taibai' and password == '123':
print('登录成功')
status_dict['username'] = username
status_dict['status'] = True
ret = f(*args, **kwargs)
return ret
else:
print('登录失败')
return inner
@auth # article = auth(article)
def article():
print('欢迎访问文章页面')
@auth
def comment():
print('欢迎访问评论页面')
@auth
def dariy():
print('欢迎访问日记页面')
article() # inner()
comment() #inner()
dariy()