推导表达式
在python中,想要得到 1-10 的数字我们可以怎么做呢。
li = []
for i in range(1,11):
li.append(i)
print(li)
输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
其实,我们还有更加简洁的写法
li = [i for i in range(1,11)]
print(li)
输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这种方法叫做列表推导。列表推到还可以和很多方法一起使用。
列表推导 + 条件判断
li = [i for i in range(1,11) if i >5]
print(li)
输出:[6, 7, 8, 9, 10]
li = [i for i in range(1,11) if i % 2 == 0]
print(li)
输出:[2, 4, 6, 8, 10]
列表推导 + 三目运算
li = [i*100 if i % 3 == 0 else i*10 for i in range(1, 10)]
print(li)
输出:[10, 20, 300, 40, 50, 600, 70, 80, 900]
列表推导 + for 嵌套
li = [i+j for i in range(1,5) for j in range(1,5)]
print(li)
输出:[2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8]
集合推导
se = {i for i in range(1,10)}
print(se)
输出:{1, 2, 3, 4, 5, 6, 7, 8, 9}
字典推导
li = {'a','b','c'}
dic = {i: j for j, i in enumerate(li)} #enumerate 是枚举,所以下标与元素配对。
print(dic)
输出:{'c': 0, 'b': 1, 'a': 2}
推导表达式相对于for循环来处理数据,要更加的方便,列表推导表达式使用更加的广泛,推导式还有很多用法,可以灵活的使用。
迭代器和生成器
列表推导式是往列表里写进数据,那么我们需要从列表中取出数据呢。首先,我们看看 for 循环在python的运行机制(底层运行方法)。
for 迭代变量 in 可迭代对象:
li = [1,2,3,4,5,6]
for i in li:
print(i)
for 循环的底层运行机制
index = 0
var = None
while index < len(li):
var = li[index]
print(var)
index += 1
每一次的循环,都会让迭代变量指向下一个元素。那么迭代对象和迭代器有什么区别呢。
迭代器
1.生成迭代器的方法
iterator = iter(li) #iter 的底层调用是python的__iter__()魔术方法。
iterator = li.__iter__() #使用python的魔术方法,生成迭代器
2.迭代器本身需要支持以下两种方法,他们一起构成迭代器协议
iterator.__iter__()
iterator.__next__()
3.取值
next(iterator)
iterator.__next__()
注意:如果迭代器值取完之后,会返回 StopIteration 错误
4.从可迭代对象生成一个迭代器
迭代器 = iter(可迭代对象)
下个值 = next(迭代器)
现在,我们在看看 for 循环实现的原理
iterable = [1,2,3,4,5]
it = iter(iterable) # 首先将可迭代对象变成迭代器
while Ture:
try:
var = next(it) #一个一个的取值
print(var)
except StopIteration: #直到没有值,跳出循环
break
可见,for 循环时从迭代器中取值,是自动循环调用 next 方法的。所有不需要手动 next 取值。
自定义迭代器:
class TestIter: #建立迭代器类
def __init__(self,li): #初始化类
self.li = li
self._index = 0
def __iter__(self): #建立迭代器
return self
def __next__(self): #建立next魔术方法
if self._index < len(self.li):
index = self.li[self._index]
self._index += 1
return index
else:
raise StopAsyncIteration #迭代器取完数据后抛出异常
a = TestIter('abcdefg')
while True:
print(a.__next__())
生成器
生成器不会把所有内容一下全部生成出来,在我们需要的时候使用 next() 去生成。
方法一:
a = (x for x in range(1,11))
print(next(a))
输出:1
print(next(a))
输出:2
print(next(a))
输出:3
注意:列表推导式的 [] 换成 ()
方法二:
def func(num):
a = 0
while a < num:
yield a
a += 1
b = func(10)
print(next(b))
输出:0
print(next(b))
输出:1
print(next(b))
输出:2
yield运行规则
yield 一个对象
暂停这个对象
等待下一个next重新激活
注意:
yield 表达式只能在函数中使用
yield 表达式可以使函数成为一个生成器
yield 可以返回表达式结果,并且暂定函数执行,直到next激活下一个yield
简单点理解生成器就是一个迭代器
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才
产生结果,而不是立即产生结果,从而节省大量的空间,这也是生成器的主要好处
补充:
a = (x for x in range(1,11))
print(dir(a))
输出:['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__',
'__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
在dir(object) 查询中,有__ iter__魔法方法,且有__ next__魔法方法的就是迭代器,只有__ iter__魔法方法的是可迭代对象。
模块,包管理器
在python中,模块就是一个 .py 文件,可以使用下面两种方法导入。
import datetime #直接导入模块
from datetime import datetime #导入模块中的datetime功能
import datetime as dt #给datetime 取别名
from datetime import datetime as dt
导入模块调用的时候需要前面加上 包名.模块名 一层一层的加上,以 . 号分隔开。包的层级划分为:包 --> 模块 --> 库 --> 方法
import time
time.sleep() #sleep前面是模块名字。
在同一目录情况下导入,可以使用上面两种方法导入。在不同目录下导入,要添加绝对路径来添加。
import 包.模块.库
直接调用方法
from 包.库. 模块 import 方法
直接调用方法
import 包
包.模块.库.方法
在python中包内有一个 __ init__.py 文件,此时才可以导入,python3 已经不请求有这个文件,也可以导入。