生成器、常见内置函数
生成器
生成器就是一种自定义的迭代器
生成器对象
# 定义阶段就是一个普通函数
def func():
print('first')
yield 111
print('second')
yield 222
print('third') # 报错,抛出异常 StopIteration 取到这里就取干净了
'''
当函数内出现yield关键字,再调用函数并不会触发函数体代码的运行,
而是将函数变成了生成器(迭代器)
'''
# 调用函数:不执行函数体代码 而是转换为生成器(迭代器)
g = func()
# print(g) # <generator object func at 0x7fca46cd2890> 生成器就是一种自定义的迭代器
res = next(g) # 每执行一个__next__代码往下运行到yield停止 返回后面的数据
print(res)
res = next(g) # 再次执行__next__接着上次停止的地方继续往后 遇到yield再停止
print(res)
next(g) # 取不到了报错
# 一出场就是一只老母猪,可以存无穷个值的类型,但每次只能拿一个
def func():
res = 1
while True:
yield res
res += 1
g = func() # 得到一个迭代器
print(next(g)) # 打印next触发代码运行,可以返回无数个值
print(next(g))
print(next(g))
自定义range功能
# for i in range(1, 10):
# print(i)
# 模仿上面的range()
def my_range(start, stop):
while start < stop:
yield start
start += 1
res = my_range(1, 10) # 调用函数:不执行函数体代码,而是转换为生成器(迭代器)
for i in my_range(1, 10):
print(i) # 结果和range效果一样
# 自定义range()模仿的更像一点
def my_range(start, stop=None, step=1):
if not stop: # 解决一个参数
stop = start
start = 0
while start < stop: # 解决二个参数
yield start
start += step # 解决三个参数
# 一个数的情况
res = my_range(10) # 不执行函数体代码,而是转换为生成器(迭代器)
for i in res:
print(i)
# 两个数的情况
res = my_range(1,10)
for i in res:
print(i)
# 三个数的情况
res = my_range(1,10,3)
for i in res:
print(i)
yield传值(了解)
def eat(name):
print('%s 准备干饭!!!'%name)
while True:
food = yield
print('%s 正在吃 %s' % (name, food))
res = eat('jason') # 并不会执行代码,而是转换成生成器
"""
send与next作用相同,都是进行下一次迭代的意思(都会解阻塞yield关键字)
send可以传递参数表示yield语句的返回值。而next不能传递参数
会先将参数当做yield语句的返回值,然后再解阻塞yield 遍历。(因此不推荐第一次遍历时使用send传参)
"""
res.__next__()
res.send('肉包子') # send的参数就是yield语句的返回值
res.send('盖浇饭')
'''
jason 准备干饭!!!
jason 正在吃 肉包子
jason 正在吃 盖浇饭
'''
yield与return对比
- yield
- 1.可以返回值(支持多个并且组织成元组)
- 2.函数体代码遇到yield不会结束而是"停住"
- 3.yield可以将函数 变成生成器 并且还支持外界传值
- 4.yield可以返回值多次
- return
- 1.可以返回值(支持多个并且组织成元组)
- 2.函数体代码遇到return直接结束
- 3. return只能返回值一次
生成器表达式
# 把列表生成式的[]换成()就是生成器表达式
res = (i for i in range(3))
print(res)
print(next(res))
print(next(res))
print(next(res))
print(next(res)) # 报错
"""
迭代器对象,生成器对象,我们都可以看成是"工厂"
只有当我们所要数据的时候工厂才会加工出"数据"
上述方式就是为了节省空间
"""
# 统计一个文件里面的字符个数
with open('a.txt',mode='rt',encoding='utf-8') as f:
res = f.read()
print(len(res))
# 考虑到如果文件过大一次读吗?可采用下面方式
# 方式一:
res = 0
for line in f: # 每次统计一行,不费内存
res += len(line)
print(res)
# 方式二:利用内置函数sum,每取一次加一次
# res = sum((len(line) for line in f))
res = sum(len(line) for line in f)
print(res)
# 生成器表达式笔试题:求和
def add(n, i):
return n + i
# 调用之前是函数 调用之后是生成器
def test():
for i in range(4):
yield i
g = test() # 初始化生成器对象
for n in [1, 10]:
g = (add(n, i) for i in g)
"""
第一次for循环
g = (add(n, i) for i in g)
第二次for循环
g = (add(10, i) for i in (add(10, i) for i in g))
"""
res = list(g)
print(res)
# A. res=[10,11,12,13]
# B. res=[11,12,13,14]
# C. res=[20,21,22,23] √
# D. res=[21,22,23,24]
常见内置函数
1、abs() 函数返回数字的绝对值
print(abs(123)) # 123
print(abs(-123)) # 123
print(abs(10.2)) # 10.2
print(abs(-10.2)) # 10.2
2、all() 用于判断给定的可迭代参数中的所有元素是否都为True,如果是返回True,否则返回False
l = [11, 22, 33, 44]
print(all(l)) # True
l = [11, 22, 33, 0] # 元素除了是 0、空、None、False外都算True
print(all(l)) # False
l = [] # 注意:空元组、空列表返回值为True,这里要特别注意。
print(all(l)) # True
3、any() 用于判断给定的可迭代参数中的所有元素有一个为True,则返回True,否则返回False
l = [1, 2, 3]
print(any(l)) # True
l = [0, '', None, False]
print(any(l)) # False
4、bin() 将int转换成二进制 oct() 将int转换成8进制 hex() 将int转换成16进制以字符串形式表示
print(bin(123)) # 0b1111011 转换成二进制
print(oct(123)) # 0o173 将int转换成8进制
print(hex(123)) # 0x7b 将int转换成16进制
5、bytes() 将字符串转换成二进制 str() 将二进制转换成字符串(需指定编码)
res = '哈哈哈'
res1 = bytes(res, 'utf8')
print(res1) # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88'
res2 = str(res1,'utf8')
print(res2) # 哈哈哈
# 编码
res1 = res.encode('utf8') # b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88'
print(res1)
# 解码
res2 = res1.decode('utf8') # 哈哈哈
print(res2)
6、callable() 于检查一个对象是否可调用的,可调用返回 True,否则返回 False
s = 'jason'
print(callable(s)) # False
def index():
pass
print(callable(index)) # True
7、chr() 根据ASCII码转数字找字符 ord() 根据ASCII码转字符找数字
print(chr(65)) # A
print(ord('Z')) # 90
8、complex() 将数字转化为复数。如果第一个参数为字符串,则不需要指定第二个参数
print(complex(1, 3)) # (1+3j) 数字
print(complex(111)) # (111+0j) 数字
print(complex('111')) # (111+0j) 当做字符串处理
9、dir() 查看当前对象可以调用的名字
print(dir()) # 获得当前模块的属性列表
print(dir([])) # 查看列表的方法
def index():
pass
print(dir(index)) # 查看函数的方法
10、divmod() 把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
print(divmod(101, 10)) # (10, 1)
"""总数据100 每页10条 10页"""
"""总数据99 每页10条 10页"""
"""总数据101 每页10条 11页"""
num,more = divmod(233,10)
if more:
num += 1
print('总共需要%s页'%num)
11、eval()只能识别简单的语法 exec()可以识别复杂语法。都是将字符串中的数据内容加载并执行
res1 = """
print('hello world')
"""
eval(res1) # hello world
exec(res1) # hello world
res = """
for i in range(10):
print(i)
"""
# eval(res) # 复杂的无法识别
exec(res) # 可以看到结果
12、isinstance() 来判断一个对象是否是一个已知的类型
print(isinstance(123, float)) # False
print(isinstance(123, int)) # True
print(isinstance(123, (str, int, list))) # 是元组中的一个返回True
13、pow() 方法返回 xy(x 的 y 次方) 的值
print(pow(2, 2)) # 4
print(pow(4, 3)) # 27
14、round() 方法返回浮点数x的四舍五入值
a = 4.6
print(round(a)) # 5
b = 4.5
print(round(b)) # 4 可以看成是五舍六入
c = 8.6
print(round(c)) # 9
15、sum() 方法对序列进行求和计算
l = [11, 22, 33, 44]
print(sum(l)) # 110