本文最后更新于:14 天前
推导表达式
得到一个元素为1到10的列表,可以怎么做?
列表
循环添加
方法一:
x = list(range(1,11))
x
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
方法二:
li = []
for i in range(1,11):
li.append(i)
li
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这是我们前面所总结过的生成一个列表的方法。
列表推导
li = [i for i in range(1,11)]
li
Out[3]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
通过列表推导,精简了代码。
运行时间对比
import time
s = time.time()
for i in range(1000000):
x = list(range(1,11))
e = time.time()
print('list: ', e-s)
f = time.time()
for i in range(1000000):
li = []
for i in range(1,11):
li.append(i)
end = time.time()
print('append: ', end-f)
ff = time.time()
for i in range(1000000):
li = [i for i in range(1,11)]
end1 = time.time()
print('[]: ', end1-ff)
list: 0.7910020351409912
append: 2.110013246536255
[]: 1.0232622623443604
可以看出列表推导的方式是比append方法更高效的,而list强制转换的是可能出现问题,所以总的来说就是推荐使用列表推导的方法。
列表推导+条件判断
l2 = [i for i in range(1,11) if i % 2 == 0]
l2
Out[4]: [2, 4, 6, 8, 10]
单独的if条件判断只能放在后面
列表推导+三目运算
l2 = [i if i % 2 == 0 else 0 for i in range(1,11)]
l2
Out[3]: [0, 2, 0, 4, 0, 6, 0, 8, 0, 10]
如果是if+else的判断条件,就需要放前面。
集合
se = {i for i in range(1,11)}
se
Out[4]: {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
字典
li = list(range(1,11))
di = {i:j for i,j in enumerate(li)}
di
Out[3]: {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
总结
推导表达式相对于for循环来处理数据,要更加的方便。
列表推导表达式使用更加的广泛。
迭代器和生成器
迭代器
列表推导是往列表中一个一个地放入数据,那如果一个一个地取出数据呢?
li = list(range(1, 11))
it = iter(li)
it2 = li.__iter__()
it
Out[3]: <list_iterator at 0x14c69f4b208>
it2
Out[4]: <list_iterator at 0x14c69f4b6a0>
生成迭代器
迭代器对象
dir(list)
sir(str)
dir(tuple)
迭代器对象本身需要支持以下两种方法,它们一起构成迭代器协议:
iterator.__iter__()
iterator.__next__()
取值
next(it)
Out[12]: 1
next(it)
Out[13]: 2
next(it)
Out[14]: 3
it.__next__()
Out[15]: 4
it.__next__()
Out[16]: 5
it.__next__()
Out[17]: 6
next(it)
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\site-packages\IPython\core\interactiveshell.py", line 3265, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-13-bc1ab118995a>", line 1, in <module>
next(it)
StopIteration
通过
next(iterator)
iterator.next()
来进行取值
注意:如果迭代器值取完之后,会返回 StopIteration 错误
自定义迭代器
class TupleIter:
def __init__(self, li):
self.li = li
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index < len(self.li):
index = self.li[self._index]
self._index += 1
return index
else:
raise StopIteration
t1 = (1, 2, 3, 4, 5)
a = TupleIter(t1)
a
Out[3]: <__main__.TupleIter at 0x1376ba4b358>
next(a)
Out[4]: 1
a.__next__()
Out[5]: 2
可以自己定义iter和next方法来自定义迭代器。
生成器
def func(n):
i = 0
while i < n:
yield i
i += 1
s = func(10)
s
Out[3]: <generator object func at 0x000001442E4FE990>
[i for i in s]
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
迭代器提供了一个实现迭代器协议的简便方法
yield 表达式只能在函数中使用,在函数体中使用 yield 表达式可以使函数成为一个生成器
def func(end):
n, a, b = 0, 0, 1
while n < end:
yield b
a, b = b, a + b
n += 1
g = func(10)
g
Out[3]: <generator object func at 0x00000238904BD990>
[i for i in g]
Out[4]: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
通过生成器就生成了一个迭代器,通过dir(g)就能查出iter和next的方法。就比我们自定义迭代器更简单。
def func(end):
n, a, b = 0, 0, 1
while n < end:
print('*'*5, a, b)
yield b
print('-' * 5, a, b)
a, b = b, a + b
n += 1
g = func(10)
next(g)
***** 0 1
Out[3]: 1
next(g)
----- 0 1
***** 1 1
Out[4]: 1
next(g)
----- 1 1
***** 1 2
Out[5]: 2
yield 可以返回表达式结果,并且暂定函数执行
通过迭代器去生成斐波拉契数列要比直接得到更加节省内存。
总结:yield只能在函数里面使用。
模块
在另一个py文件中的对象如何导入到当前的py文件中呢?
模块
在python中,模块就是一个py文件,可以使用下面两种方法导入
import
from import
from import as
import datetime
from datetime import datetime (as this_datetime)
在同一目录下,可直接使用上面两种方法去导入;在不同目录下,需要使用 sys.path 添加路径
sys.path.append(‘path’)
from pages import a
a.demo()
不同的文件夹导入模块可以用这个两种方式。
在python3中导入后,会在当前路径下生成一个__pycache__ 文件夹
sys模块
sys 模块提供了与python解释器交互的函数,在python中它是始终可以导入使用的.
sys.argv
import sys
print(sys.argv)
$ python b.py 123 456
['b.py', '123', '456']
获取终端命令行输入
sys.path
import sys
print(sys.path)
解释器模块导入查找路径
if__name__ == ‘__main__‘:
__name__
python会自动的给模块加上这个属性
如果模块是被直接调用的,则 name 的值是 __main__否则就是该模块的模块名
pages.a a
__main__ b
注意
if __name__ == ‘__main__‘: 该语句可以控制代码在被其他模块导入时不被执行
__main__ b
包和包管理
如果模块太多了,怎么方便的去管理呢?
包概念
把很多模块放到一个文件夹里面,就可以形成一个包.
包管理
当把很多模块放在文件中时,为了方便引用包中的模块,引入了包管理
__init__.py
在包管理中,加入此模块,则包名可以直接通过属性访问的方式,访问此模块内的对象,此模块不加上可能不会报错,但是规范是要加上,文件内容可以为空
相对路径导入
在包管理中,可以通过. (一个点) 和 .. (两个点)分别来导入同层和上一层的模块
引入作用
在包中,如果包中模块要导入同一包中的其他模块,就必须使用此方法导入.
使用方法
from .module(..module) import obj (as new_name)
引入之后的影响
当一个模块中出现此导入方式,则该模块不能被直接运行,只能被导入
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!