python生成器对象&常见内置函数


内容概要

  • 异常捕获(补充)
  • for循环本质
  • 生成器
  • yield 和 return优缺点
  • 笔试题
  • 常用内置函数

内容详细

一、异常捕获补充

try:
    print(name)
except NameError as e:
    print('接收类型错误')
except Exception:
    print('接收所有错误类型')
else:
    print('代码出错的时候才会执行这段代码')
finally:
    print('无论代码出不出错,都会执行这段自代码')
    

# 主动报错,一般用于监控某些代码运行到一定峰值的时候报警
raise NameError

# 插入,判断一个变量名是否为指定类型
name = 'elijah'
assert isinstance(name, str)

二、for循环本质

# in 后面的的可迭代对象调用__iter__方法转为迭代器对象
# 开启循环,打印迭代器对象调用__next__方法取出来的值
# 做异常处理,当值被取完之后会报错,报错处理是break退出循环

l = [11, 33, 44, 55, 66, 77]

res = l.__iter__()
while True:
    try:
        print(res.__next__())
	except Exception:
        break

# for 循环
for i in l:
    print(i)

三、索引取值与迭代器对象取值

迭代器取值:
	优:
    	1.不依赖于索引的一种通用取值方式
	缺:
    	1.取值的顺序永远都是固定从左往右,无法重复获取
索引取值:
	缺:
        1.需要提供有序容器类型才可取值(不是一种通用的方式)
    优:
    	1.可以重复取值

四、生成器对象

'''
生成器是自定义的迭代器,和迭代器一样,都是相当于一个“工厂”,只在需要数据的时候调用__next__方法取出数据,节省内存空间
'''


'''列表生成式'''
l = ['elijah', 'jason', 'kevin', 'egon']
res = [f'{i}_DSB' for i in l]
print(res)  # ['elijah_DSB', 'jason_DSB', 'kevin_DSB', 'egon_DSB']

'''字典生成式'''
l = ['elijah', 'jason', 'kevin', 'egon']
l1 = [30000, 40000, 50000, 60000]

res1 = {j: l1[i] for i, j in enumerate(l)}
print(res1)  # {'elijah': 30000, 'jason': 40000, 'kevin': 50000, 'egon': 60000}

# 没有元组生成式,加括号的是生成器
l = ['elijah', 'jason', 'kevin', 'egon']
res2 = (i for i in l)

while True:
    try:
        print(res2.__next__())
    except Exception:
        break

'''yield关键字'''
def genorates():
    print('first code')
    yield 
    print('second code')
    yield


'''
当函数体内有yield关键字,那么在第一次调用函数的时候
并不会执行函数体代码,而是将函数变成了生成器(迭代器)
'''
res = genorates()
print(res.__next__())

 
'''
函数代码执行碰到yield,只会停止不会立刻结束,直至函数代码运行结束
'''

# yield传值
def eat(name):
    print('%s 准备干饭!!' % name)
    while True:
        food = yield
        print('%s 正在吃 %s' % (name, food))

res = eat('elijah')  # 并不会执行代码  而是转换成生成器
res.__next__()
res.send('肉包子')  # 给yield传值
res.send('盖浇饭')

五、笔试题

def run(n, i):
    return n + i

def test():
    for i in range(4):
    	yield i

        
g = test()

for n in [1, 10]:  # 别把[1, 10]看成range(1, 10), 这是个只有两个元素的列表
    g = (run(n, i) for i in g)
'''
循环两次:
	1.n=1, g = (run(n, i) for i in g)
	2.n=10,g= (run(n, i) for i in (run(n, i) for i in g))
'''
# 运行两遍,相当于  g = (run(n, i) for i in (run(n, i) for i in g))
# 因为生成器在未调用之前把它当成一个式子


res = list(g)
print(res)

六、yield 和 return

yield
	1.可以返回值(支持返回多个并组织成元组)
	1.yield可以将函数变成生成器,并且支持外界传值
    2.只是让函数'停止',不会结束
return
	1.可以返回值(支持多个并组织成元组)
	1.运行函数遇到return即停止

七、内置函数

# 1.abs()  取绝对值

abs(123)
abs(-123)

# 2.chr()  ord()
chr(97)  # a   =>  返回数字对应的字符串
ord('A')   # 65    =>  返回字符串对应的ASCII表数字


# 3.isinstance(name, str)
判断变量名是否是指定的数据类型

# 4.callable(func)
判断变量名是否是可运行的函数名

# 5.all()   any()

l = [1, 2, 3, 0]

all(l)   ->  False, 当容器里所有的值都是True时才返回True
any(l)   ->  True, 只要容器里有一个值是True,就会返回True

# 6.bin()  oct()  hex()  进制数
print(bin(123))  # 转为二进制 0b1111011
print(oct(123))  # 转为十进制 0o173	
print(hex(123))  # 转为十六进制 0x7b

# 7.bytes()   str()
res = '选择方向,有效努力'
res1 = bytes(res, 'utf8')  # 把字符串按照指定编码转换成二进制数,第一个传入变量名参数,第二个是字符编码
print(res1) 
res2 = str(res1, 'utf8')
print(res2)

# 8.complex() 复数
print(complex(123))  # (123 + 0j)

# 9.dir()  查看当前对象可以调用的名字
def index():
    pass

print(dir(index))  # ['__dict__', '__dir__', '__doc__'......]

# 10.divmod()   
print(divmod(101, 10))
print(divmod(233, 10))


# 小应用:10条数据为一页,有233条数据,要分多少页
def count(nums, num):
    c1, c2 = divmod(nums, num)
    if c2:
        c1 += 1
    print('需要分 %s 页' % c1)


count(233, 10)


# 11.eval() 只能识别简单的语法, exec()可以识别复杂语法,都是将字符串中的数据内容加载,如果识别到可执行的python语法会执行

res = '''
for i in range(5):
    print(i)
'''
exec(res)  # 打印0,1,2,3,4

res = '''
print('hello, world!')
'''
eval(res)  # hello, world!


# 12.pow(a, b)   求a的b次方
pow(3, 3)  # 27

# 13.round()  五舍六入
print(round(4.8))  # 5
print(round(4.6))  # 5
print(round(4.5))  # 4

# 14.sum()  求总和

l = [11, 22, 33, 44, 55, 66, 77]
print(sum(l))

生成器对象知识仿造range()

# 生成器形式
def my_range(start, stop=None, step=1):
    if not stop:
        stop = start
        start = 0
    while start < stop:
        yield start
        start += 1


res = my_range(10)  # 需要注意的是,含有yield关键字函数第一次运行只是转换成生成器对象
print(res.__next__())  # 依次取值
print(res.__next__())
print(res.__next__())
print(res.__next__())

# 易错点

print(my_range(10).__next__())
print(my_range(10).__next__())
print(my_range(10).__next__())

'''
这样子其实是每次都重新把函数转换成一个新的生成器对象,所以每次都只能取到第一个值
'''