Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数

Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数

一丶生成器

本质:

​ 就是迭代器

生成器产生的方式:

​ 1.生成器函数 👇

​ 2.生成器表达式 👇

​ 3.python内置函数或者模块提供(其实1,3两种本质上差不多,都是通过函数的形式生成,只不过1是自己写的生成器函数,3是python提供的生成器函数 如: map() filter() zip()等等)

生成器与迭代器的区别:

​ 生成器是我们自己用python代码构建的.迭代器可以使用iter() , __ iter __()进行取值

二丶生成器函数

####只要函数中出现了yiled ,那么就是一个生成器函数.(生成器)
## 一个next 对应一个yield
def func():			#当出现了yiled就是不再是函数了就是生成器函数
    print(111)
    print(111)
    print(111)
    print(111)
    yield 2         	# yield的作用是,yield后面的值 给了next取值
    yield 3
    yield 4
    yield 5

ret=func()     			# 生成器对象 赋给变量ret
print(ret)     			# 生成器对象地址 <generator object func at 0x0000018ACC20EF68>
print(ret.__next__())		# ret执行__next__()方法 取值 2
print(ret.__next__())		# ret执行__next__()方法 取值 3			
print(next(ret))			# ret执行__next__()方法 取值 4   next()方法的本质还是__next__()
print(next(ret))			# ret执行__next__()方法 取值 5
print(next(ret))  		 # 当 生成器对象中没有值可以取的时候就会报错---> StopIteration

三丶yiled与return的区别

return:

​ 结束函数,给函数的执行者返回值,多个值通过元组返回,

yiled:

​ 不结束函数 ,(暂停函数) . 对应着给next返回值 , 多个值通过元组返回

# return
def func():

    return 1,2,3,4

print(func())


#  yield   
def func():

    yield 1,2,3,4       # yield后面跟一个列表就返回一个列表,返回多个值就是返回一个元组

print(func().__next__())

四丶send(了解)

# next只能获取yield生成的值,但是不能传递值。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')
​
dog = gen('alex')
next(dog)
next(dog)
next(dog)
​
​
# 而使用send这个方法是可以的。
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield 222
        print(f'{name} start to eat {food}')
​
dog = gen('alex')
next(dog)  # 第一次必须用next让指针停留在第一个yield后面
# 与next一样,可以获取到yield的值
ret = dog.send('骨头')
print(ret)
​
​
def gen(name):
    print(f'{name} ready to eat')
    while 1:
        food = yield
        print(f'{name} start to eat {food}')
​
dog = gen('alex')
next(dog)
# 还可以给上一个yield发送值
dog.send('骨头')
dog.send('狗粮')
dog.send('香肠')




############# 此处, 先看看, 之后会补充含义


#send和next()区别:
#        相同点:
#           send 和 next()都可以让生成器对应的yield向下执行一次。
#            都可以获取到yield生成的值。

#        不同点:
#            第一次获取yield值只能用next不能用send(可以用send(None))。
#            send可以给上一个yield置传递值。

五丶生成器的应用

##生成器应用 ,现在你需要一个服装工厂给你加工2000件衣服,

###可迭代对象
#老板很实在,一下给你准备好了2000件衣服
def func()
    li=[] 
    for i in range(1,2001):
           li.append(f'{i}件衣服')
    return li

print(func())                  # 老板的工厂中一半的场地都用来堆积2000衣服

# 总结,  加工2000个衣服, 假如说加工一件1秒, 你现在需要2000秒才能加工完成.  而且加工完的衣服必须有地方放置. 耗时耗空间.  但是比较很直观,2000个衣服就在工厂里囤放.  换到程序角度来说: 你需要2000条数据,你的内存中就存放了2000个数据.  不管你用多少,这2000条数据就会在内存是实实在在的占2000个位置. so 占内存大.




###生成器
#加工厂老板,给你准备好了加工衣服的传送带, 夸张一些加工一件衣服1秒.

def func():						  #生成器函数,  相当于创建一个加工流水线
    for i in range(1,2001):	
        yield print(f'{i}件衣服')   #yield返回数据, 相当于把加工的衣服给来拿衣服的你   
gen_obj = func() 			 	  #把生成器给了一个变量, 确保每次来加工时,都是这个流水线(预定)


###需求: 现在你需要200件衣服,老板立马给你制作了200件衣服 ,剩下的1800件还在待加工的状态.
for i in range(200):      # 你拿了200件 ,执行了200次拿的动作 
    gen_obj.__next__()    # 在当前的这个流水线(当前的这个生成器),每次拿一件(每次取一个数据)

    
###需求: 现在你需要400件衣服,老板立马从剩余的1800件衣服中又制作了400件衣服给你,现在这个流水线还剩1200 
for l in range(400):     # 老板从你预定的流水线继续加工400件
    next(gen_obj)        # 还是在当前的这个流水线(当前的这个生成器),每次拿一件(每次取一个数据)
   

# 总结, 你预定了2000件衣服, 老板没有给你一起直接加工出来,每当你来拿衣服的时候你需要多少个,老板给你咔咔咔把你需要多少个衣服加工出来.  优势:1.对于老板的工厂来说,不占地方, (对于程序来说,不占内存,需要多少条,就生成多少条,内存中就占这么多,并且一点数据取出来(next)就销毁.) 2.对加衣服的你也没有影响.(不影响本身程序的调用)



##创建200个生成器函数   --->相当于创建了200流水线
for i in range(200): 		 #  生成200个生成器函数
    print(func().__next__(),type(func()))   # 所以每次打印的都是 1
    

六丶yiled与yiled from

##yield 
 def func():
     li=[1,2,3,4]
     yield li   # yield 返回一个值    , 若是yield后跟多个值,就以元组的形式返回

 ret =func()
 print(next(ret))  # 返回一个列表的值(只能得到一个值,next只接一次,不管你是元组 或 列表都是一个值返回)
 print(next(ret))  # 报错 StopIteration




##yield from  可以把 后面的可迭代的对象进行拆分,依次给next取值. 
def func():
    li=[1,2,3,4]
    yield from li   # yield from 把可迭代对象拆分, 简化for循环, 
    '''
    #表面现象
     yield 1   
     yield 2   
     yield 3   
     yield 4   
    '''
 ret =func()
 print(next(ret))  #  1
 print(next(ret))  # 2
 print(next(ret))  # 3
 print(next(ret))  # 4





#### yield 与yield from 对比 ####

# yield : 对应next ,给next 返回值
# yield from 将一个可迭代对象的每一个元素返回给next
# yield from 节省代码 ,提升效率

七丶列表推导式,生成器表达式(字典的推导式,集合推导式)

列表推导式:

​ 一行代码构建一个有规律比较复杂的列表。(👇看代码.不废话)

####两种构建方式:
# 1.循环模式: [变量(加工后的变量) for 变量 in iterable]
# 2.筛选模式: [变量(加工后的变量) for 变量 in iterable if 条件]

######循环模式
##需求:循环 100以内的所有的值
#平常做法
li=[]
for i in range(1,101):
    li.append(i)
print(li)

#列表推导式
print([i for i in range(1,101)])



######筛选模式   复杂程度不能超过3级
##案例1:三十以内可以被2整除的数。
print([i for i in range(1,31) if i%2==0])

#案例2: 找到嵌套列表中名字含有两个‘e’的所有名字(有难度)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
##普通做法
li=[]
for el in  names:
    for el2 in el:
        if el2.count('e')>=2:
            li.append(el2)
print(li)

##列表推导式
print([name for el in names for name in el if name.count('e')>=2])

      
      
####列表推导式的优缺点
    #优点:简单 快捷
    #缺点:可读性不高,不好拍错
    # 慎用,不用入迷
    

生成器表达式:

​ 一行代码构建一个生成器。(👇看代码.不废话)

####两种构建方式:
# 1.循环模式: (变量(加工后的变量) for 变量 in iterable)
# 2.筛选模式: (变量(加工后的变量) for 变量 in iterable if 条件)

####循环模式
obj=(i for i in range(10))
print(obj)  	 	#<generator object <genexpr> at 0x000001972E9CEF68>

#如何触发生成器(迭代器 )取值? 
    # 1.  next()   ,  __next__()    逐个取值
    # 2 . for      循环 遍历取值   哪个简单不用多说了吧
    # 3 . list
 for  i in obj:
    print(i)

    
    
####筛选模式
obj=(i for i in range(10) if x%2==0)
print(obj)          #<generator object <genexpr> at 0x000001999105FF68>


字典的推导式: (创建模式同上👆,一行解决)

####两种构建方式:
# 1.循环模式: {变量(加工后的变量) for 变量 in iterable}
# 2.筛选模式: {变量(加工后的变量) for 变量 in iterable if 条件}


li= ['小潘', '第三部','金馆长', '宋老板']

#普通创建字典
dic={}
for k,i in enumerate(li):
    dic[k]=i
print(dic)

#字典推导式
print({k:i for k,i in enumerate(li)})

集合推导式:(创建模式同上👆,一行解决)

####两种构建方式:
# 1.循环模式: {变量(加工后的变量) for 变量 in iterable}
# 2.筛选模式: {变量(加工后的变量) for 变量 in iterable if 条件}
#集合推导式
print({i for i in range(101)})

八丶内置函数

什么是内置函数:

​ 由python解释器提供的一些特别的方法,目的提高开发效率

内置函数的数量:

​ 目前:内置函数 68种

👇看代码吧:

# -*- coding: utf-8 -*-
# Author  : Ds

#eval() 剥去字符串外衣  执行代码
 s1='1+3'
 ret=eval(s1)  #去除两端字符,数字相加得到结果
 print(ret)

#exce()  也是执行代码流,
 s3='''
 for i in range(10):
     print(i)
 '''
 exec(s3)  # 执行for循环

##建议👉: 不要不轻易使用这个两个内置函数. 都是会将代码执行,
        #假如给了一个字符串的病毒,使用这两个方法任意执行.你的电脑都会中毒




#hash() 得到一个哈希值
 print(hash(123))   # 数字的哈希值还是数字
 print(hash('abc'))
 print(hash('abcdkjahfduai'))





#help()查看方法,
 print(help(str.upper()))





#callable() 判断是不是一个可调用的对象
# 如果返回 True,object 仍然可能调用失败;但如果返回 False,调用对象 object 绝对不会成功。

def abc():
    pass

a=123
b='123'

print(callable(abc),dir(abc))  # '__call__'
print(callable(a))
print(callable(b))




#bin()  oct()  hex()
print(bin(100))  # 将十进制转化成二进制。              逢2进一
print(oct(10)) # 将十进制转化成八进制字符串并返回。      逢8进一
print(hex(17)) # 将十进制转化成十六进制字符串并返回。    逢16进一

# 二进制
# 只有  0 1 两个数字,  逢2进一

#八进制
#  0 - 7  ,  逢8进一

#十六进制
#0 - 9 , a-f表示 10 -15   逢16进一






#divmod() 计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)  分页用到
print(divmod(10, 3))





#round()保留小数位   四舍五入
print(round(3.123))





# pow()  x**y   x的y次幂
print(pow(2,3))




#ord() 输入字符寻找其在unicode的位置。
print(ord('a'))
print(ord('中'))




# chr()  输入位置数字找出其对应的字符
print(chr(98))  #
print(chr(20104))  # 予




#repr() 原形毕露  保留字符串格式
print('不打广告')
print(repr('不打广告'))

msg = '我叫%r' %('不打广告')
print(msg)




#all()  函数用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE
#any()  函数用于判断给定的可迭代参数 iterable 是否全部为 False,
# 0,'',[],{},set(),(),None 都是False

l1 = [1, 'fgdsa', [], {1: 2}]
l2 = [0, '', [], {}]
print(all(l1)) # 判断可迭代对象元素全部都为True,返回True
print(any(l2))  # 判断可迭代对象元素只要有一个True返回True






九丶匿名函数

定义:

​ 没有名字的函数 ,lambda表达式 ,匿名函数只能构建简单的函数 ,

#普通模式, 定义函数
 def func(a,b):
    return a+b

#匿名函数构建 
#格式--->    lambda关键字  传参   :  返回值
func2=lambda x,y:x+y
print(func2(1,2))

# 写匿名函数:接收一个可切片的数据,返回索引为 0与2的对应的元素(元组形式)。
#匿名函数最常用的就是与内置函数结合使用

#1.
 func3=lambda argv : tuple(argv[0:3:2])
 print(func3([1,2,3,4]))

#2.
 func3=lambda x : (x[0],x[2])
 print(func3('你好啊的'))

#3.
 func4=lambda x,y : x if x>y else y
 print(func4(1,2))

#4.
 func4=lambda  *args : max(args)
 print(func4(1,2,3,4,5))

posted @ 2019-06-20 22:08  染指未来  阅读(167)  评论(0编辑  收藏  举报