13.py

Posted zhao110

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了13.py相关的知识,希望对你有一定的参考价值。

一. 昨日内容回顾
1.函数名
赋值.
作为列表的元素
参数
返回值
函数名就是变量
2. 闭包
内层函数对外层函数的局部变量的访问
1. 安全
2. 常驻内存
3. 迭代器
可迭代对象: __iter__() Iterable
迭代器: __iter__() __next__() Iterator
特点:
1.节省内存
2.惰性机制
3.只能往前拿
可迭代的内容:
str, list, dict, tuple, set, range
f

二. 今日主要内容
1. 生成器和生成器函数
生成器的本质就是迭代器
生成器的三种创建办法:
1.通过生成器函数
2.通过生成器表达式创建生成器
3.通过数据转换
生成器函数:
函数中包含了yield的就是生成器函数
注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行
生成器表达式:
(结果 for 变量 in 可迭代对象 if 筛选)
取值:
1. __next__()
2. send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值
3. 可以for循环
4. list(g)
2. 各种推倒式和生成器表达式
1. 列表推倒式 [结果 for 变量 in 可迭代对象 if 筛选]
2. 字典推倒式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key:value
3. 集合推倒式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key

先整理.然后再做作业.
预习:
内置函数(68个)
生成器函数
 def func():
# print("我是周杰伦")
# yield "昆凌" # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数
# print("我是王力宏")
# yield "李云迪???"
# print("我是笛卡尔积")
# yield "笛卡尔积是谁"
# print("你好啊") # 最后一个yield之后如果再进行__next__() 会报错
# g = func()
# print(g.__next__())
# print(func().__next__())

# g1 = func()
# g2 = func()
# print(g1.__next__())
# print(g1.__next__())
#
# print("==============")
# print(g2.__next__())

#
# g = func() # 通过函数func()来创建一个生成器
# print(g.__next__()) # 周杰伦
# print(g.__next__()) # 王力宏
# print(g.__next__()) # 笛卡尔积
# print(g.__next__())

# return 直接返回结果. 结束函数的调用
# yield 返回结果.可以让函数分段执行
#
# def func():
# lst = []
# for i in range(1,100001):
# lst.append("衣服%s" % i)
# return lst
#
# def gen():
# i = 1
# while i < 100001:
# yield "衣服%s" % i
# i = i + 1
# g = gen()
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())
# print(g.__next__())

#
# def func():
# yield 11
# yield 22
# yield 33
# yield 44
#
#
# g = func() # 拿到的是生成器. 生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环
#
# for i in g:
# print(i) # 本质上执行的是__next__()
#
# it = g.__iter__()
# while True:
# try:
# print(it.__next__())
# except StopIteration:
# break
send
def func():
# print("大碴粥")
# a = yield "11"
# print(a)
# print("狗不理")
# b = yield "22"
# print(b)
# print("大麻花")
# c = yield "33"
# print(c)
#
# g = func()
# print(g.__next__())
# print(g.send(1))
# print(g.send(2))
# print(g.send(3))

# __next__() 可以让生成器向下执行一次
# send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个不能用send(). 最后一个也不要传值


def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "大饼"
print("b=",b)
c = yield "韭菜盒子"
print("c=",c)
yield "GAME OVER"

gen = eat() # 获取?成器

ret1 = gen. __next__ ()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send("猫粮")
print(ret4)


def func():
yield 11
yield 22
yield 33
yield 44
g = func()
lst = list(g) # 可迭代对象
print(lst)
推导式



# lst = [i*i for i in range(1,101) if i % 3 == 0]
# 3. 寻找名字中带有两个e的?的名字
# names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘ , ‘Andrew‘ , ‘Wesley‘ , ‘Steven‘ ,
# ‘Joe‘],[‘Alice‘, ‘Jill‘ , ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘ , ‘Eva‘]]
# lst = [name for first in names for name in first if name.count("e") == 2]
# print(lst)
#
# print([name for i in names for name in i if name.count(‘e‘)==2])



# lst = ["衣服%s" % i for i in range(10000)]

生成器表达式
# g = (i for i in range(10))
# print(list(g))

# gen = ("麻花藤我第%s次爱你" % i for i in range(10))
# for i in gen:
# print(i)

# 生成器的惰性机制
# def func():
# print(111)
# yield 222
# g = func()
# g1 = (i for i in g)
# g2 = (i for i in g1)
#
# print(list(g))
# print(list(g1))
# print(list(g2))
字典推导式
# dic = {"a":"b", "c":"d"}
# # 把字典中的key:value互换 .{"b":"a", "d":"c"}
# new_dic = {dic[key]:key for key in dic}
# print(new_dic)

# lst1 = ["alex", "wusir", "taibai", "ritian"]
# lst2 = [‘sb‘, "很色", "很白", "很牛"]
# # {"alex":"sb", "wusir":"很色"}
#
# dic = { lst1[i]:lst2[i] for i in range(len(lst1))}
# print(dic)
合集推导式

lst = ["马化腾", "马化腾", "王建忠", "张建忠", "张建忠", "张雪峰", "张雪峰"]

s = {i for i in lst} # 集合推倒式
print(s)

元祖是不能推倒的:应为元祖是不可以改变的

本节主要内容:
1. ?成器和?成器函数
2. 列表推导式
?. ?成器 什么是?成器. ?成器实质就是迭代器. 在python中有三种?式来获取?成器:
1. 通过?成器函数
2. 通过各种推导式来实现?成器
3. 通过数据的转换也可以获取?成器 ?先, 我们先看?个很简单的函数:
def func(): print("111") return 222 ret = func() print(ret)
结果: 111 222 将函数中的return换成yield就是?成器 def func(): print("111") yield 222 ret = func() print(ret)
结果: 运?的结果和上?不?样. 为什么呢. 由于函数中存在了yield. 那么这个函数就是?个?成器 函数.
这个时候. 我们再执?这个函数的时候. 就不再是函数的执?了. ?是获取这个?成器. 如何使?呢?
想想迭代器. ?成器的本质是迭代器. 所以. 我们可以直接执?__next__()来执? 以下?成器.
def func(): print("111") yield 222 gener = func() # 这个时候函数不会执?.
?是获取到?成器 ret = gener.__next__() # 这个时候函数才会执?. yield的作?和return?样.
也是返回 数据 print(ret) 结果: 111 222 那么我们可以看到, yield和return的效果是?样的. 有什么区别呢?
yield是分段来执??个 函数. return呢? 直接停?执?函数.
def func():
print("111")
yield 222
print("333")
yield 444
gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__() # 最后?个yield执?完毕.
再次__next__()程序报错, 也就是 说.
和return?关了. print(ret3)
结果: 111 Traceback (most recent call last):
222 333 File "/Users/sylar/PycharmProjects/oldboy/iterator.py",
line 55, in 444 ret3 = gener.__next__() # 最后?个yield执?完毕.
再次__next__()程序报错, 也 就是说. 和return?关了. StopIteration 当程序运?完最后?个yield.
那么后?继续进?__next__()程序会报错. 好了?成器说完了. ?成器有什么作?呢?
我们来看这样?个需求. 老男孩向JACK JONES订 购10000套学?服. JACK JONES就比较实在.
直接造出来10000套衣服.
def cloth():
lst = [] for i in range(0, 10000):
lst.append("?服"+str(i))
return lst
cl = cloth() 但是呢, 问题来了.
老男孩现在没有这么多学?啊. ?次性给我这么多. 我往哪?放啊. 很尴尬 啊.
最好的效果是什么样呢? 我要1套. 你给我1套. ?共10000套.
是不是最完美的. def cloth(): for i in range(0, 10000):
yield "?服"+str(i)
cl = cloth()
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
区别: 第?种是直接?次性全部拿出来. 会很占?内存.
第?种使??成器. ?次就?个. ?多 少?成多少. ?成器是?个?个的指向下?个.
不会回去, __next__()到哪, 指针就指到哪?. 下?次继续获取指针指向的值.
接下来我们来看send?法, send和__next__()?样都可以让?成器执?到下?个yield.
def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "?饼"
print("b=",b)
c = yield "?菜盒?"
print("c=",c)
yield "GAME OVER"
gen = eat() # 获取?成器
ret1 = gen.__next__()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send("猫粮")
print(ret4)
send和__next__()
区别: 1. send和next()都是让?成器向下走?次
2. send可以给上?个yield的位置传递值, 不能给最后?个yield发送值.
在第?次执?? 成器代码的时候不能使?send()
?成器可以使?for循环来循环获取内部的元素:
def func():
print(111)
yield 222
print(333)
yield 444
print(555)
yield 666
gen = func()
for i in gen:
print(i)
结果: 111 222 333 444 555 666
?. 列表推导式, ?成器表达式以及其他推导式 ?先我们先看?下这样的代码, 给出?个列表, 通过循环,

向列表中添加1-13 : lst = [] for i in range(1, 15): lst.append(i) print(lst)
替换成列表推导式: lst = [i for i in range(1, 15)] print(lst) 列表推导式是通过??来构建你要的列表,
列表推导式看起来代码简单. 但是出现错误之 后很难排查. 列表推导式的常?写法:
[ 结果 for 变量 in 可迭代对象]
例. 从python1期到python14期写入列表lst: lst = [‘python%s‘ % i for i in range(1,15)] print(lst)
我们还可以对列表中的数据进?筛选 筛选模式:
[ 结果 for 变量 in 可迭代对象 if 条件 ] # 获取1-100内所有的偶数
lst = [i for i in range(1, 100) if i % 2 == 0] print(lst)
?成器表达式和列表推导式的语法基本上是?样的.
只是把[]替换成() gen = (i for i in range(10)) print(gen) 结果:
at 0x106768f10> 打印的结果就是?个?成器.
我们可以使?for循环来循环这个?成器:
gen = ("麻花藤我第%s次爱你" % i for i in range(10)) for i in gen: print(i)
?成器表达式也可以进?筛选: # 获取1-100内能被3整除的数
gen = (i for i in range(1,100) if i % 3 == 0) for num in gen: print(num) #
100以内能被3整除的数的平?
gen = (i * i for i in range(100) if i % 3 == 0) for num in gen: print(num) #
寻找名字中带有两个e的?的名字 names = [[‘Tom‘, ‘Billy‘, ‘Jefferson‘, ‘Andrew‘, ‘Wesley‘, ‘Steven‘, ‘Joe‘],
[‘Alice‘, ‘Jill‘, ‘Ana‘, ‘Wendy‘, ‘Jennifer‘, ‘Sherry‘, ‘Eva‘]] #
不?推导式和表达式 result = [] for first in names: for name in first: if name.count("e") >= 2: result.append(name) print(result) #
推导式 gen = (name for first in names for name in first if name.count("e") >= 2) for name in gen: print(name)
?成器表达式和列表推导式的区别:
1. 列表推导式比较耗内存.
?次性加载. ?成器表达式?乎不占?内存.
使?的时候才分 配和使?内存
2. 得到的值不?样. 列表推导式得到的是?个列表.
?成器表达式获取的是?个?成器. 举个栗?.
同样?篮?鸡蛋. 列表推导式: 直接拿到?篮?鸡蛋. ?成器表达式:
拿到?个老?鸡. 需要 鸡蛋就给你下鸡蛋. ?成器的惰性机制: ?成器只有在访问的时候才取值.
说?了. 你找他要他才给你值. 不找他 要. 他是不会执?的.
def func():
print(111)
yield 222
g = func() # ?成器g g1 = (i for i in g) # ?成器g1.
但是g1的数据来源于g g2 = (i for i in g1) # ?成器g2.
来源g1 print(list(g)) # 获取g中的数据. 这时func()才会被执?. 打印111.获取到222. g完毕. print(list(g1))
# 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据 了 print(list(g2)) # 和g1同理
深坑==> ?成器.
要值得时候才拿值. 字典推导式: 根据名字应该也能猜到.
推到出来的是字典 # 把字典中的key和value互换
dic = {‘a‘: 1, ‘b‘: ‘2‘} new_dic = {dic[key]: key for key in dic} print(new_dic) #
在以下list中. 从lst1中获取的数据和lst2中相对应的位置的数据组成?个新字典
lst1 = [‘jay‘, ‘jj‘, ‘sylar‘] lst2 = [‘周杰伦‘, ‘林俊杰‘, ‘邱彦涛‘]
dic = {lst1[i]: lst2[i] for i in range(len(lst1))} print(dic)
集合推导式: 集合推导式可以帮我们直接?成?个集合.
集合的特点: ?序, 不重复. 所以集合推导式? 带去重功能
lst = [1, -1, 8, -8, 12] #
绝对值去重 s = {abs(i) for i in lst} print(s)
总结: 推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式 ?成器表达式:
(结果 for 变量 in 可迭代对象 if 条件筛选) ?成器表达式可以直接获取到?成器对象.
?成器对象可以直接进?for循环. ?成器具有 惰性机制. ?个?试题.
难度系数500000000颗星:
def add(a, b):
return a + b
def test():
for r_i in range(4):
yield r_i
g = test() for n in [2, 10]: g = (add(n, i) for i in g) print(list(g))

友情提?: 惰性机制, 不到最后不会拿值 这个题要先读?下. 然后??分析出结果. 最后?机器跑?下. 



















































































































































































































































































































































































以上是关于13.py的主要内容,如果未能解决你的问题,请参考以下文章

杂谈13.py

笨办法学Python(十三)

流程控制--while

习题13 参数解包和变量

python manage.py startapp app 时候报错No module named _sqlite3

去除空格,水平制表符:CHAR换行符:CHAR(10)回车符:CHAR(13)