nums = [1,2,3,4,5]
num_sqrt = [x*x for x in nums]
print(num_sqrt)
-----------------
[1,4,9,16,25]
#有限制的一维列表推导式
nums = [1,2,3,4,5]
num_sqrt = [x*x for x in nums if x&1==1]
print(num_sqrt)
-----------------
[1,9,25]
nums = [[1,2,3,4,5],[6,7,8,9,10]]
num_sqrt = [x for xx in nums for x in xx]
print(num_sqrt)
--------------------
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#有限制的二维列表推导式
nums = [[1,2,3,4,5],[6,7,8,9,10]]
num_sqrt = [x for xx in nums for x in xx if x&1==1]
print(num_sqrt)
-------------------
[1, 3, 5, 7, 9]
def fun(x):
return x*x
nums = [1,2,3,4,5]
#返回一个字典类型
num_sqrt = map(fun,nums)
print(num_sqrt)
a = [x for x in num_sqrt]
print(a)
----------------------
<map object at 0x000001D26306BC50>
[1, 4, 9, 16, 25]
import sys as sys
a = [x for x in range(1,1000)]
iter_a = iter([x for x in range(1,1000)])
print(sys.getsizeof(a),sys.getsizeof(iter_a),sep='\n')
------------------------------------
9024
56
像我们经常使用的一些数据结构:列表、元组…… 他们里面的数据都是实实在在地在我们的内存中,这是一种 显式 存储,当数据非常大的时候,我们的内存是吃不消的。这个时候就需要使用迭代器这样的 隐式 存储方式,节省了大量的内存空间。这个对处理大数据很有帮助的。
#next 访问迭代器,像一个只会向后移动的指针,遍历过的不会在遍历
print(next(iter_a))
print(next(iter_a))
print(next(iter_a))
#for 循环也可以
b = iter([1,2,3])
a = [x for x in b]
print(a)
print(next(b))
---------------------
1
2
3
[1, 2, 3]
Traceback (most recent call last):
File "f:\C-and-Python-Algorithn\python\practice.py", line 47, in <module>
print(next(b))
StopIteration
#迭代器以遍历完,最后一条语句没有用
使用了 yield 的函数被称为生成器generator
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
def fibonacci(n): # 生成器函数 - 斐波那契
a, b, counter = 0, 1, 0 # a,b是数列的相邻的两个元素,counter计数器
while True:
if (counter > n-1): # 当循环到指定次数之后退出循环
break
yield a # 函数会停止并返回a的值,并保存下来a,b,counter的值
a, b = b, a + b # 更新a,b的值
counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
print(type(f))
while True:
try:
#print(next(f))
print (next(f), end=" ") # 依次访问f的内容
except StopIteration: # 这个就是刚才那个迭代器遍历结束后还访问会出现的错误
break
------------------------------
<class 'generator'>
0 1 1 2 3 5 8 13 21 34
a = [1,2,3,4]
b = a
print(a==b)
print(id(a),id(b))
#实际上并没有将列表赋值给新的参数b,只是他两个指向同一个地址
#切片复制
a = [1,2,3,4,5]
b = a[:]
print(id(a),id(b))
-----------------------
True
2435637701448 2435637701448
2435637701512 2435635979528
import copy
#浅拷贝
a = [1,2,3,4,5]
b = copy.copy(a)
print(id(b),id(a))
a = [[1,2,3],[4,5,6],[7,8,9]]
b = copy.copy(a[1])
a[0][0] = 100
print(a,b)
a[1][0] = 100
print(a,b)
print(id(a[1]),id(b))
--------------------------------
[[100, 2, 3], [4, 5, 6], [7, 8, 9]] [4, 5, 6]
[[100, 2, 3], [100, 5, 6], [7, 8, 9]] [4, 5, 6]
3000896580296 3000896580360
#深拷贝
a = [[[1,2,3],2,3], [4,5,6]]
b = copy.deepcopy(a)
print(a,b)
print(id(a),id(b))
------------------------------
[[[1, 2, 3], 2, 3], [4, 5, 6]] [[[1, 2, 3], 2, 3], [4, 5, 6]]
2297174288648 2297174288904
#断言
# 添加参数
'''
当表达式为True时,正常执行
当表达式为False时,抛出异常
'''
assert len([1,2,3])<3, "列表长度不大于3"
---------------
Traceback (most recent call last):
File "f:\C-and-Python-Algorithn\python\practice.py", line 119, in <module>
assert len([1,2,3])<3, "列表长度不大于3"
AssertionError: 列表长度不大于3
a = [1,2,3]
b = [11,22,33]
c = zip(a, b) # 返回的是一个迭代器,不能下标访问
for i in c:
print(i)
for i, j in zip(a, b): # zip经常这样使用
print(i, j)
a = [1,2,3,4,5]
b = [11,22,33] # 长度不一样
c = [x for x in zip(a, b)] # 以最短的那个列表为返回值长度
print(c)
a = [1,2,3]
b = [11,22,33]
c = [111,222,333]
d = [x for x in zip(a,b,c)] # 多列表也可以压包
print(d)
------------------
(1, 11)
(2, 22)
(3, 33)
1 11
2 22
3 33
[(1, 11), (2, 22), (3, 33)]
[(1, 11, 111), (2, 22, 222), (3, 33, 333)]
#解包
a = (1,2,3)
b = [11,22,33]
c = {'a':1, 'b':2, 'c':3}
print(*a)
print(a)
print(*b)
print(b)
print(*c) # 对于字典只是解压它的key
print(c)
# **双星号用来解压字典
print("{b} {c} {a}".format(**c))
# 直接print(**c)时会报错的
li = [1,2,3,4,5]
x, *y, z, p = li
print(x, y, z, p)
------------------
1 2 3
(1, 2, 3)
11 22 33
[11, 22, 33]
a b c
{'a': 1, 'b': 2, 'c': 3}
2 3 1
1 [2, 3] 4 5
args和 *kwargs是常用的两个参数
*args:用于接受多余的未命名的参数,元组类型。
**kwargs:用于接受形参的命名参数,字典类型的数据。
解包的意义就是将传递给函数的一个列表,元组,字典,拆分成独立的多个元素然后赋值给函数中的参变量。
解压字典有两种解发,一种用解的只有key,一种用*解的有key,value。但是这个方法**只能在函数定义中使用。