python基础篇笔记03 迭代器、生成器、推导式、内置函数

 
 
D13 迭代器、生成器
 
 
1.迭代器
 
  我们可以对 list,tuple,dict等类型的数据使用for循环从其中依次拿取数据进行使用,我们把这样的过程称为遍历。也叫迭代。
 
  可迭代对象: 把可以通过for循环迭代读取数据的对象称为可迭代对象。(都必须有 ‘__iter__’ 方法,即可迭代协议
   
  常见可迭代对象:  str , list , tuple , set , dict , f1文件句柄 , itertor迭代器(迭代器也是可迭代对象)
 
  dir(obj)  对象的所有操作方法
  可迭代对象的 dir(obj)里都有'__iter__'这个方法,可以用来判断是否是可迭代的
    if ‘__iter__’ in dir(obj)
     通常如此判断: from collections import Iterable (Iterator)从模块引包                   
               isinstance(obj ,  Iterable)
 
  迭代器:
  在对数据迭代使用的过程中,都有个带状态的对象来帮助我们记录数据访问的位置。我们把这个帮助我们进行迭代的对象叫做迭代器
  (卡qia子zi)
      (迭代器必须有'__iter__', '__next__' 方法,即迭代器协议)  .__iter__() 返回迭代器自身, .__next__() 返回下一个值
 
       迭代器优点:  1、节省内存空间  2、满足惰性机制  3、不会反复取值
       附: try: ...... except: ....... 异常处理    (默认Exception 所有异常)
 
       可迭代对象转化成迭代器:iterob.__iter__()  console结果  iterator obj...
                       迭代器含有 __iter__   、 __next__  、 遵循迭代器协议
  
 
for循环原理:
  (上卡qia子zi)
 
 
2. 生成器    一种特殊的迭代器。(自主构建的特殊迭代器
 
  python中,生成器是一次生成并返回一个对象(生成器对象,它是一个特殊的迭代器),可将其视为可恢复函数
 
  简单的说,就是在函数的执行过程中,yield语句会把你需要的对象return返回给调用生成器的地方,然后hold保留状态退出函数,
  生成器内的所有变量参数都会被保存起来供下一次使用。下一次调用生成器函数的时候又从上次中断的地方( hold点)开始执行。 
         

  在python中有三种方式来构建生成器:

    1. 通过生成器推导式  g = (lambda x: x*i for i in rang(4))

    2. 通过生成器函数  yield 语句(相当于...return + hold...RH下次取值先找 hold点

              yield  生成值

              生成器函数+():只是代表一个生成器对象,并不是函数执行;

                      可理解为惰性机制,在不执行函数的前提下,获得(返回)该生成器对象

    3. python内置函数或者模块提供(其实2,3两种本质上差不多,都是通过函数的形式生成,

      只不过2是自己写的生成器函数,3是python提供的生成器函数而已)

def func():

    print("111")

    yield 222

gener = func() #  ()这个时候函数不会执行,()而是获取到生成器

ret = gener.__next__() # 这个时候函数才会执行, 也可以用 next(gener)

print(ret)

运行结果:

111

222
示例
  使用生成器获取生成值
    1. 使用 g.__next__()
    2. 使用 next(g)
    3. 使用 g.send()  (见下文)
 
 
  生成器函数(代表了生成器对象,即有生成器函数出现的地方就只是代表了该生成器对象,并不是函数执行。)
 
       第一 : 函数中只要有 yield ,就是特殊函数,是生成器函数
       第二 : 一个 yield 对应一个 __next__
 
          
 
 
 
   for  i  in  xxx  :  这个过程,就是将(可迭代对象)(容器)(迭代器)(生成器)xxx 中的元素挨个拿出来给临时的 i 
 
  关于生成器send:
#!/usr/bin/env python
# -*- coding:utf-8 -*-


def gen(name):
    print(f'{name} ready to eat')
    n = 100
    while 1:
        food = yield n
        print(food)
        print(f'{name} start to eat {food}')
        n = n + 1


dog = gen('alex')
# 第一次必须用next让指针停留在第一个yield后面 或者 send(None)

ret = dog.send('骨头')
# 与__next__一样,可以获取到yield的值
# 还可以在本次执行__next__的过程中传入一个值,供生成器使用

print(ret)
示例1
#!/usr/bin/env python
# -*- coding:utf-8 -*-


def gen_demo():
    value = yield 1
    yield value


gen = gen_demo()
print(next(gen))
print(gen.send("I am Value!"))
示例2

  

  其实,send和next的执行很像,只是send可以和生成器互动,传入一个值。

 
 3.推导式、解析

  列表推导式分为两种模式:

    1.循环模式:[变量(加工的变量) for 变量 in iterable]

    2.循环筛选模式: [变量(加工的变量) for 变量 in iterable if 条件]

1 li1 = [i for i in range(10)]
2 li2 = [f'神舟{i}号' for i in range(1, 9)]
3 li3 = [i for i in range(30) if i % 3 == 0]

  

  生成器表达式和列表推导式的语法上一模一样,只是把 [ ] 换成 ( ) 就行了。

  生成器推导式和列表推导式的区别:

    1.列表推导式比较耗内存,所有数据一次性加载到内存。而.生成器表达式遵循迭代器协议,逐个产生元素。

    2.得到的值不一样,列表推导式得到的是一个列表.生成器表达式获取的是一个生成器

    3.列表推导式一目了然,生成器表达式只是一个内存地址

 

# 字典推导式 dic = {lst1[i]:lst2[i] for i in range(len(lst1))}

# 集合推导式 s = {abs(i) for i in lst} 

 
 
D14 内置函数
 
 
 
  函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,
  他们不仅效率高(底层都是用C语言写的),而且是拿来即用,避免重复造轮子,那么这些函数就称为内置函数
 
eval()  执行字符串类型的代码,并返回代码执行后最终结果。  
exec()  执行字符串类型的代码,无返回值,即返回None  ---> 用于流程语句。
eval('2 + 2')   # 4

s = '''
for i in [1,2,3]:
    print(i)
'''
exec(s)
View Code
 
hash()  获取一个对象(可哈希对象:int,str,Bool,tuple)的哈希值。
     字典的键Key唯一本质是指键Key哈希值唯一。
     hash(True)、hash(1)同为1,hash(False)、hash(0)同为0,所以对于字典,True跟1 是同名键,False跟0 是同名键。
dict1 = {True: 'alex', 1: 'wusir'}
print(dict1[True])    # wusir
print(hash(True), hash(1)) # 1 1
View Code
help()  用于查看函数或模块用途的详细说明。
callable()  用于检查一个对象是否是可调用的。如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。
int()  用于将一个字符串或数字转换为整型。
print(int())
print(int('12'))
print(int(3.9))    # 并没有四舍五入
print(int('0100', base=2))
运行结果:
0
12
3
4
View Code

float()  用于将整数和字符串转换成浮点数。

complex()  用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不能传入第二个参数。

print(float(3))
print(complex(1))
print(complex(1, 2))
print(complex('3+4j'))
print(complex('12'))
运行结果:
3.0
(1+0j)
(1+2j)
(3+4j)
(12+0j)
View Code
bin()  十进制整数转二进制字符串(<class 'str'>)      
oct()  十进制整数转八进制字符串   
hex()  十进制整数转十六进制字符串
print(bin(-10))
print(oct(250))
print(hex(250))
运行结果:
-0b1010
0o372
0xfa
View Code
divmod(x, y)  x除y,返回元组(商,余数)     
round()  保留浮点数小数点位数,四舍五入                 
pow(x,y,z=1)  x的y次幂,再对z取余(取模)
print(divmod(7, 3))
print(round(7 / 3))  # 默认不保留小数
print(round(7 / 3, 2))
print(round(2.333501, 3))  # 四舍五入
print(pow(2, 3))
print(pow(2, 3, 3))
运行结果:
(2, 1)
2
2.33
2.334
8
2
View Code

bytes() 编码(编成 B码)。  str() 解释 B码

s1 = '你好'  # 字符串'你好',两个字符'你'、'好'
bs1 = s1.encode('utf-8')  # 编码=编译成字节码:把字符串中对字符编译成指定字节码 'utf-8'码
print(bs1)  # b'xe4xbdxa0xe5xa5xbd'
s1b = bs1.decode('utf-8')  # 解码=解释字节码:把特定字节码按照指定方式解释出来,解释成字符。(方式要一致才可)
print(s1b)  # 你好
bs2 = bytes(s1, encoding='utf-8')  # 编码
print(bs2)  # b'xe4xbdxa0xe5xa5xbd'
bs3 = bytes(s1, encoding='gbk')
print(bs3)  # b'xc4xe3xbaxc3'
print(bs3.decode('gbk'))  # 你好

# 可用str()来进行解码操作,解释字节码=用指定方式把特定字节码转化成字符(串)。
s2 = str(bs2, encoding='utf-8')
print(s2)  # 你好
s3 = str(bs3, encoding='gbk')
print(s3)  # 你好
View Code

ord()  输入字符找该字符Unicode编码的位置(万国码)。

chr()  输入Unicode位置数字找出其对应的字符。

print(ord('A'))       # 65
print(ord(''))     # 20013
print(chr(97))      # a
print(chr(20013))  #
View Code

repr()  返回一个对象的string形式(原形毕露)。

dict1 = {'a': 1, 'b': 2}
str1 = "abc哟!"
str2 = repr(dict1)
str3 = repr(str1)
print(str2, type(str2))
print(str3, type(str3))

运行结果:
{'a': 1, 'b': 2} <class 'str'>
'abc哟!' <class 'str'>
View Code
enumerate(IterObj,n)   枚举函数
  对于一个可迭代对象,将其各个元素枚举编号打包成元组(),组成序列。编号从n开始
list1 = ['a', 'b', 'c']
for i in enumerate(list1):
    print(i)
for i, j in enumerate(list1):
    print(i, j)
for i, j in enumerate(list1, 10):
    print(i, j)
运行结果:
(0, 'a')
(1, 'b')
(2, 'c')
0  a
1  b
2  c
10  a
11  b
12  c
View Code
 
all()  全为真才为真,相当于and
any()  有一个为真即为真,相当于or
print()  屏幕输出
''' 源码分析
def print(self, *args, sep=' ', end='
', file=None): 

    """
    print(value, ..., sep=' ', end='
', file=sys.stdout, flush=False)
    file:  默认是输出到屏幕,如果设置为文件句柄,输出到文件
    sep:   打印多个值之间的分隔符,默认为空格
    end:   每一次打印的结尾,默认为换行符
    flush: 立即把内容输出到流文件,不作缓存
    """

'''print(111,222,333,sep='*')    # 111*222*333
print(111,end='')
print(222)    # 两行的结果 111222
​
f = open('log','w',encoding='utf-8')
print('重要学习资料...',file=f,flush=True)
# 运行结果:屏幕无输出,log文件里写入了内容:'重要学习资料...'
View Code

list()  将一个可迭代对象转换成列表

tuple()  将一个可迭代对象转换成元组

dict()  通过相应的方式创建字典。

l1 = list('abcd')
tu1 = tuple('abcd')
print(l1, tu1)
运行结果:
['a', 'b', 'c', 'd'] ('a', 'b', 'c', 'd')
View Code

abs()  求绝对值

sum()  求和

print(sum([1, 2, 3]))
print(sum((1, 2, 3), 100))
运行结果:
6
106
View Code

min()  求最小值

max()  求最大值

print(min(-1, 0, 1))
print(min([1, 2, 3]))  # 返回此序列的最小值
print(min((-1, 2, 5), key=abs))
          # 加key是可以加函数名,就是加比较法则。
          # 就是将需要做比较的各元素,按照key所代表的函数法则进行最小值比较,最终仍旧返回对应的原始元素。
          #(即将各元素传参给法则函数,对返回值进行最小值比较)。
print(min(-2, -1, 2, 5, key=lambda x: abs(x)))  # 可以设置多个参数比较大小。
dic = {'a': 1, 'b': 2, 'c': 3}
print(min(dic, key=lambda x: dic[x]))  
          # x为dic的键,函数法则就是键对应对值做最小值比较,最终返回对应对原始键。
运行结果:
-2
1
-1
-1
a
View Code

reversed()  翻转。若将一个序列翻转, 返回翻转序列的迭代器;序列即列表。

l1 = reversed('你好')
l2 = reversed((1, 2, 3, 4))
l3 = reversed([1, 2, 3, 4])
print(l1, type(l1))
print(l2, type(l2))
print(l3, type(l3))
print(list(l1), list(l2), list(l3))
运行结果:
<reversed object at 0x0000000002193408> <class 'reversed'>
<reversed object at 0x0000000002193448> <class 'reversed'>
<list_reverseiterator object at 0x0000000002193488> <class 'list_reverseiterator'>
['', ''] [4, 3, 2, 1] [4, 3, 2, 1]
View Code

sorted()  排序,可以通过key加函数制定排序规则

语法:  
  sorted(iterable,key=None,reverse=False)

iterable : 可迭代对象

key: 排序规则函数,sorted会将可迭代对象中的所有元素根据排序规则进行排序,(即将所有元素都传递给排序规则函数,按照运算的结果进行排序),
   经过规则排序后,sorted最终返回对应的原始元素的排序。

reverse :是否是倒序,True 倒序 False 正序

lst = [1,3,2,5,4]
lst2 = sorted(lst)
print(lst)    #原列表不会改变
print(lst2)   #返回的新列表是经过排序的
 
 
lst3 = sorted(lst,reverse=True)
print(lst3)   #倒序
 
结果:
[1, 3, 2, 5, 4]
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]

字典使用sorted排序

dic = {1:'a',3:'c',2:'b'}
print(sorted(dic))   # 字典排序返回的就是键的排序
 
结果:
[1,2,3]




和函数组合使用

# 定义一个列表,然后根据一元素的长度排序
lst = ['天龙八部','西游记','红楼梦','三国演义']
 
# 计算字符串的长度
def func(s):
    return len(s)
print(sorted(lst,key=func))
 
# 结果:
# ['西游记', '红楼梦', '天龙八部', '三国演义']


和lambda组合使用

lst = ['天龙八部','西游记','红楼梦','三国演义']
 
print(sorted(lst,key=lambda s:len(s)))
 
结果:
['西游记', '红楼梦', '天龙八部', '三国演义']
 
 
lst = [{'id':1,'name':'alex','age':18},
    {'id':2,'name':'wusir','age':17},
    {'id':3,'name':'taibai','age':16},]
 
# 按照年龄对学生信息进行排序
 
print(sorted(lst,key=lambda e:e['age']))
 
结果:
[{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]
View Code

zip()  拉链方法。多个可迭代对象作为参数,功能:将多个对象中的元素按照索引对应拉在一起,组成元组,每个元组里都有一个这些可迭代对象的元素;返回一个迭代器

       若各个可迭代对象的元素个数不一致,则按照个数最少的返回。

lst1 = [1, 2, 3]
lst2 = ['a', 'b', 'c', 'd']
lst3 = ('', '', '', '', '')
print(zip(lst1, lst2, lst3))
for i in zip(lst1, lst2, lst3):
    print(i)

运行结果:
<zip object at 0x00000000021C3648>
(1, 'a', '')
(2, 'b', '')
(3, 'c', '')
View Code
filter()  筛选过滤函数  
  filter(func,xxx) xxx为可迭代对象
  将xxx中的每个元素依次实例化传参给函数func,筛选出xxx中满足条件的原始元素组成一个新的迭代器返回的是一个迭代器;
  func必须为条件函数,即func必须返回bool值,根据bool真假筛选,传递出xxx中条件判断为真的原始元素,组成一个新迭代器。
语法: filter(function,iterable)

function: 用来筛选的函数,在filter中会自动的把iterable中的元素传递给function,然后根据function返回的True或者False来判断是否保留此项数据

iterable:可迭代对象

lst = [{'id': 1, 'name': 'alex', 'age': 18},
       {'id': 1, 'name': 'wusir', 'age': 17},
       {'id': 1, 'name': 'taibai', 'age': 16}, ]

ls = filter(lambda d: d['age'] > 16, lst)

print(ls, type(ls))
print(list(ls))

运行结果:
<filter object at 0x00000000021C3948> <class 'filter'>
[{'id': 1, 'name': 'alex', 'age': 18}, {'id': 1, 'name': 'wusir', 'age': 17}]
View Code
map()  映射函数  
  map(func,xxx) xxx为可迭代对象
  将xxx中的每个元素依次实例化传参给函数func,传出经过函数处理的运算结果给一个新的迭代器,可看作加工。返回是一个迭代器
  func 必须为执行函数,即必须有返回值,map会传递出函数func 的返回值,组成一个新迭代器。
映射函数

语法: map(function,iterable)  功能:对可迭代对象中的每一个元素进映射,分别去执行function,执行结果组成一个迭代器。


计算列表中每个元素的平方,返回新列表

lst = [1,2,3,4,5]
​
def func(s):
​
    return  s*s
​
mp = map(func,lst)
​
print(mp)
​
print(list(mp))

结果:
<map object at 0x00000000023E34C8>
[1, 4, 9, 16, 25]

改写成lambda

lst = [1,2,3,4,5]
​
print(list(map(lambda s:s*s,lst)))


计算两个列表中相同位置的数据的和

lst1 = [1, 2, 3, 4, 5]
​
lst2 = [2, 4, 6, 8, 10]
​
print(list(map(lambda x, y: x+y, lst1, lst2)))
​
结果:
​
[3, 6, 9, 12, 15]
View Code

reduce()  递减函数

from functools import reduce
def func(x,y):
    return x + y
​
# reduce 的使用方式:
# reduce(函数名, 序列)  # 这两个参数必须都要有,缺一个不行
​
ret = reduce(func,[3,4,5,6,7])
print(ret)  # 结果 25


reduce的功能:先把序列中的前俩个元素取出计算出一个值然后临时保存着,接下来用这个临时保存的值和序列中第三个元素进行计算,
求出一个新的值将前面的临时值覆盖掉,然后在用这个新的临时值和列表中第四个元素计算,依次类推...最后reduce返回一个最终值。
​
注意:我们放进去的序列没有更改

以上这个例子我们使用sum就可以完全的实现了.我现在有[1,2,3,4]想让列表中的数变成1234,就要用到reduce了.

普通函数版
from functools import reduce
​
def func(x,y):
​
    return x * 10 + y
    # 第一次的时候 x是1 y是2  x乘以10就是10,然后加上y也就是2最终结果是12然后临时存储起来了
    # 第二次的时候x是临时存储的值12 x乘以10就是 120 然后加上y也就是3最终结果是123临时存储起来了
    # 第三次的时候x是临时存储的值123 x乘以10就是 1230 然后加上y也就是4最终结果是1234然后返回了
​
ret = reduce(func,[1,2,3,4])
print(ret)

​结果:
1234
​
匿名函数版
l = reduce(lambda x,y:x*10+y,[1,2,3,4])
print(l)



在Python2.x版本中recude是直接 import就可以的, Python3.x版本中需要从functools这个包中导入

龟叔本打算将 lambda 和 reduce 都从全局名字空间都移除, 舆论说龟叔不喜欢lambda 和 reduce

最后lambda没删除是因为和一个人写信写了好多封,进行交流然后把lambda保住了.
View Code

参考资料:https://www.processon.com/view/link/5b4ee15be4b0edb750de96ac

compile()  编译函数  
      语法:compile(str,'','exec')  将一个字符串编译为字节代码对象。         
 
format()  其中的数字格式化
bytearry()  字节数组          
memoryview()  内存对象    
ascii()  判断是否是ASCII码表中的字符
 
 
                                              
3. 匿名函数
 
  匿名函数,顾名思义就是没有名字的函数。lambda是定义匿名函数的关键字,相当于函数的def。
 
  Func1 = lambda 参数1参数2返回值 
       
   
                
 
 
 
 
 
come on!
 
all()   全为真才为真,相当于and
any()   有一个为真即为真,相当于or
原文地址:https://www.cnblogs.com/kingon/p/11802454.html