推导式
推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一 个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持
列表推导式
基本格式:variable = [out_exp_res for out_exp in input_list if out_exp == 2]
# result = [i*1 for i in range(20) if i %3]
# print(result)
# import math
# #使用列表推导式输出100以内,开平方是整数的数
# result = [i for i in range(100) if (math.sqrt(i)%1) == 0]
# print(result)
# #对列表中的数取两位小数
# list1=[2.45345,4.3455325,82.234324,9.841234]
# result1 = [round(i,2) for i in list1]
# print(result1)
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva', 'Elven']]
for i in names:
for j in i:
if j.lower().count('e') >= 2:
print(j)
result = [j for i in names for j in i if j.lower().count('e') >= 2]
print(result)
集合推导式
str1 = "fjklfjlkefjl jfso"
print(set(str1))
print({ i for i in str1})
字典推导式
基本格式:variable = {out_key:out_value for out_key,out_value in input_list if out_exp == 2}
#字典推导式
# print({x:y for x,y in [('a',1),('b',2)]})
#统计字符串中每一个字符出现的次数
# str1 = "dsfjhdsfjksdhfhdsfhkds"
# dict1 = {}
# for i in set(str1):
# dict1[i] = str1.count(i)
# print(dict1)
# print({i:str1.count(i) for i in set(str1)})
#过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
# q1 = ['a','ab','abc','abcd','abcde']
# for i in q1:
# if len(i) >3:
# print(i.upper())
#
# print([i.upper() for i in q1 if len(i) > 3])
#求(x,y)中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表
# print([(x,y) for x in range(6) for y in range(6) if x%2 == 0 and y % 2])
# 快速更换key和value
# q3 = {'a':10,'b':34}
# print({y1:x1 for x1,y1 in q3.items()})
#合并大小写对应的value值,将k统一成小写
# q4 = {'B':3,'a':1,'b':6,'c':3,'A':4}
# print({x2.lower():q4.get(x2.lower(),0)+q4.get(x2.upper(),0) for x2 in q4})
总结
-
列表推导式只能构建比较负责并且有规律的列表
-
超过三层循环才能构建成功的,就不建议用列表推导式
-
查找错误(debug模式)不行
python可迭代对象
容器
容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not in关键字判断元素是否包含在容器中。
通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如 迭代器和生成器对象)
可迭代对象
凡是可以返回一个迭代器的对象都可称之为可迭代对象
可迭代对象有哪些
-
容器都是可迭代对象
-
此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。
-
凡是可以返回一个迭代器(iter)的对象都可称之为可迭代对象
-
str,list,文件,range
如何确认一个对象是不是可迭代对象
iter方法
可迭代对象实现了iter方法,该方法返回一个迭代器对象
b = [1,2,3]
dir(b)
输出包含:[……,'__iter__',……]
使用Iterable判断
迭代器
实现了__iter__
()和__next__
()的都是迭代器
#__iter__
方法 返回自身 #__next__
方法 返回下一个值
-
迭代器一定是一个可迭代对象
-
for循环 -- 先调用对象的
__iter__
方法得到一个迭代器 -
在调用
__next__
方法,不断返回下一个值 -
容器中没有更多的元素了,则抛出StopIteration
-
for循环中遇到异常就退出
-
懒加载,惰性求值,用的时候才生成
# print(dir([1,2,3]))
# print(hasattr([1,2,3],'__next__'))
lst = [1,2,3]
lst_it = lst.__iter__()
lst_it2 = iter(lst)
print(hasattr(lst_it2,'__next__'))
print(lst_it.__next__())
print(next(lst_it))
#取完会抛出StopIteration的异常
#编写迭代器,实现range
class MyRange():
def __init__(self,num):
self.num = num
self.tmp = -1
def __iter__(self):
return self
def __next__(self):
if self.tmp < self.num-1:
self.tmp+=1
return self.tmp
else:
raise StopIteration q
生成器
-
特殊的迭代器
-
就是为了写迭代器更加简单,优雅
-
不需要手动实现
__iter__
和__next__
方法
生成器表达式
#1.生成器表达式
lst = [4,5,6]
g1 = (x*2 for x in lst)
print(dir(g1))
print(next(g1))
生成器函数
yield关键字
保留中间算法,下次继续执行
#当调用next时,遇到yield就暂停运行,并且放回yield后面表达式的值
#当再次调用yield时,就会从刚才暂停的地方继续运行,直到遇到下一个yield或者整个生成器结束
#2.生成器函数
#yield关键字
def get_content():
print("start yield.")
yield 3
print("second yield.")
yield 4
print("end.....")
g1 = get_content()
print(dir(g1))
print(next(g1))
print(next(g1))
def Myrange(num):
i = 0
while i< num:
yield i
i +=1
for i in Myrange(15):
print(i)
生成器的好处
-
可以用更少地中间变量写流式代码
-
相比其它容器对象它更能节省内存
-
可以用更少的代码来实现相似的功能
列表推导式 与生成器表达式的区别
写法上:【】()
iterable iterator
三种关系小结
-
对象是可迭代对象, 但却不一定是迭代器
-
如果对象属于迭代器, 那么这个对象一定是可迭代的
-
迭代器实现了一个
__next__
()方法,可以通过next函数每次取出迭代器中的每个元素 • -
迭代器对象:
__iter__
()返回的是迭代器对象自身。 -
生成器是一种特殊的迭代器
send 数据
除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个 新的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出 生成器
必须要激活之后的生成器才能用send,也就是说要先执行了一次next之后才能用send修改数据
def counter():
count = 1
while 1:
val = yield count
print(f'val is {val}')
if val is not None:
print(f'val is {val}')
count = val
else:
count += 1
count = counter()
# count.sent(10) #修改数据,必须先激活生成器,可以使用next激活
print(next(count))
print('*'*20)
print(count.send(10)) #返回一个新的值给yield count
print('*'*20)
print(next(count))
手动关闭当前生成器,关闭之后就不能再生成值了
count.close() #手动关闭当前生成器,关闭之后就不能再生成值了,否则会报错
print(next(count))
yield 与 yield from
def f1():
yield range(10)
def f2():
yield from range(4) #后面一定要接一个可迭代对象
iter1 = f1()
iter2 = f2()
print((iter1))
print((iter2))
print(next(iter1))
print(next(iter2))
特大文件处理
生成器 + 切割多个小文件并行处理
怎么确保文件传完了,可以使用哈希算法(md5sum)
哈希算法
单向加密 明文--》密文 1.验证文件完整性 2.验证登录,加密传输