#list
#元素訪問
li = []
print(li[0])
print(li[-1])
print(li[-2])
查找元素位置
li.index(element)
如果element不在li中會拋出異常,因此不確定一定要用try-except捕捉
添加元素
li.append(element)
li.append(element)
#合併list
list1.extend(list2)
注意append作爲一個元素,extend則是直接合並拼接。
# 示例 append() extend()的區別
>>> l1 = [1,2,3,'hello']
>>> l2 = ['world',5,6,7]
>>> l1.append(l2)
>>> l1
[1, 2, 3, 'hello', ['world', 5, 6, 7]]
>>>
>>> l1 = [1,2,3,'hello']
>>> l1.extend(l2)
>>> l1
[1, 2, 3, 'hello', 'world', 5, 6, 7]
>>>
Empty 和 None 不是一回事
l3 = []
>>> if not l3:
... print('Empty')
...
Empty
>>> if l3 is None:
... print('None')
...
>>>
>>> [] == None
False
>>>
空和None不是一回事,空只是沒有元素,但在內存中還是要爲這對象容器分配一些信息。
而None則表示什麼都沒有。
so 在Python中判斷容器爲空,一般用法:if not object: 或 if len(object)==0
list迭代
for i in list1: # 迭代器
pass
for i in range(len(list1)): #索引
list1[i]
for j in range(i+1, len(list1)):
pass
range(n) 就是 range(0,n) 就是 [0, n-1]
一般除非必須獲取索引的場景,否則不使用索引方式,因爲可以通過特定元素獲取索引,list.index() 或通過enum()方法
函數返回值 tuple() or list[]
return a, b 就相當於返回元組tuple(a, b), 因此是不可更改的
也可以明確返回list[], 即 return [a, b]
tuple 元組
相當於是 const list,使用 ( ) 表示
dict 字典 , dict無序, value可以是各種複合數據類型list,tuple,dict都行
d = {}
d = {'a':1, 'b':2, 1:'one', 2:'two'}
d = dict(key = value, key = value...)
通過key訪問value
>>> d = { 'b':2, 'a':1, 2:'two' , 1:'one', 'comp':[1,2,'hello'] }
>>> d[1]
'one'
>>> d['a']
1
>>> d['comp']
[1, 2, 'hello']
>>>
# 判斷元素是否存在, 依賴 key, 對於dict看不到value任何信息,唯一知道的就是key
>>> 'b' in d
True
>>> 'c' in d
False
>>> 'two' in d
False
>>>
>>> len(d)
5
# 添加元素
d[newKey] = value
# 遍歷
>>> for key in d:
... print(d[key])
...
2
1
two
one
[1, 2, 'hello']
>>>
>>> for key,value in d.items():
... print(key, value)
...
b 2
a 1
2 two
1 one
comp [1, 2, 'hello']
>>>
>>> for k in d.keys():
... print(d[k])
...
2
1
two
one
[1, 2, 'hello']
>>>
>>> for k in d.keys():
... print(k, d[k])
...
b 2
a 1
2 two
1 one
comp [1, 2, 'hello']
set集合, 元素無重複
s_a = set([1,2,3,4,5,4,5,6,7,7])
s_b = set([4,5,4,5,6,7,7])
>>> s_a
{1, 2, 3, 4, 5, 6, 7}
>>> len(s_a)
7
>>> s_b = set([4,5,4,5,6,7,7])
# >>> s_b = {4,5,4,5,6,7,7} 或者像dict使用{ }
# 聲明空 set
s3 = set()
>>> s_b
{4, 5, 6, 7}
# 判斷元素是否存在
(element in set)
# 交集、 並集 或用方法 set.intersection() set.union()
>>> s3 = set()
>>> len(s3)
0
>>> s4 = s_a | s3 # s_a.untion(s3)
>>> s4
{1, 2, 3, 4, 5, 6, 7}
>>>
>>> s5 = s_a & s3 # s_a.intersection(s3)
>>> s5
set()
>>> len(s5)
0
>>> s_a & s_b
{4, 5, 6, 7}
>>>
# 差集
(s_a - s_b) # s_a.difference(s_b)
# 差集 A - (A & B)
print(s_a - s_b)
print(s_a.difference(s_b))
# 對稱差 (A | B) - (A & B)
print(s_a ^ s_b)
print(s_a.symmetric_difference(s_b))
序列類型切片slice [start: end: steps] 表示範圍左閉右開[start, end) 且steps缺省 = 1
>>> l1 = list(range(10))
>>> l1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l1[5:7]
[5, 6]
>>>
# end超過實際大小(越界),會按照實際大小計算
# 負值
# end邊界, 最後一個元素對應-1, 倒數第二個對應-2 ; 因此可以利用切片特性,進行逆序遍歷,快速翻轉reverse
list[::-1]
>>> l1[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>>
# 切片是生成一個新的對象,原list不變
列表推導式
case1 使用列表推導式完成同樣功能:生成0-20的偶數
'''
li = []
for i in range(20):
if(i%2)==0:
li.append(i)
print(li)
'''
>>> li = [i*2 for i in range(10)]
>>> l1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l2 = [i%2==0 for i in range(20)]
>>> l2
# 問題? 如何在列表推導式中用if過濾條件? 答案如下
>>> l2 = [i for i in range(20) if i%2==0]
>>> l2
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>
# 列表推導式生成dict
>>> dict2 = {x:x%2==0 for x in range(20)}
>>> dict2
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False, 10: True, 11: False, 12: True, 13: False, 14: True, 15: False, 16: True, 17: False, 18: True, 19: False}
>>>
二維數組
li_2d = [[0] * 3] * 3
>>> li_2d
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> li_2d[0][0] = 100
>>> li_2d
[[100, 0, 0], [100, 0, 0], [100, 0, 0]]
>>>
# 思考: 爲什麼修改[0][0]卻改變了3個元素? 因爲使用的引用,三行實際是隻有一份,引用了3次,淺拷貝
li_2d = [ [0] * 3 for i in range(3)] # 這樣纔是深拷貝
>>> li_2d
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> li_2d[0][0] = 200
>>> li_2d
[[200, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> len(li_2d)
3
>>>
生成器
問題的提出
- 場景:創建一個巨大的列表而僅僅需要訪問其中少量幾個元素
- 如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?
這樣就不必創建完整的list,從而節省大量的空間
實際使用時纔去生成,把真正的計算推遲到你使用的時候,生成器就是爲了解決惰性計算問題
# case1 平方表
square_table = []
for i in range(10000):
square_table.append(i*i)
square_generator = (x*x for x in range(50000))
for i in range(10):
print(next(square_generator))
>>> type(square_generator)
<class 'generator'>
>>>
>>> output
0
1
4
9
16
25
36
49
64
81
>>> print(next(square_generator))
100
>>> print(next(square_generator))
121
>>> print(next(square_generator))
144
>>>
>>> range(10)
range(0, 10)
在python3中range()函數就是這樣的
# case2 以菲波那切數列爲例
def fib(limit):
n, a, b = 0, 0, 1
while n < limit:
yield b
a, b = b, a + b
n += 1
return 'done'
f=fib(5)
type(f)
print(next(f))
<class 'generator'>
>>> print(next(f))
1
>>> print(next(f))
1
>>> print(next(f))
2
>>> print(next(f))
3
>>> pr
生成器、迭代器、可迭代的概念
可以直接作用於for循環的對象,統稱爲可迭代對象:Iterable
可以被next()調用並不斷返回下一個值得對象成爲迭代器:Iterator
(強調特性:惰性計算序列, 因此generator一定是Iterator)
Iterable屬性的對象一定是Iterator,即Iterator ->(充分不必要)-> Iterable
from collections import Iterable
from collections import Iterator
>>>
>>> isinstance([1,2,3], Iterable)
True
>>> isinstance([1,2,3], Iterator)
False
>>> isinstance({}, Iterable)
True
>>> isinstance({}, Iterator)
False
>>> isinstance('abcd', Iterable)
True
>>> isinstance('abcd', Iterator)
False
>>> isinstance(1234, Iterable)
False
>>> isinstance(1234, Iterator)
False
>>> g = (x*x for x in range(10))
>>> type(g)
<class 'generator'>
>>> isinstance(g, Iterable)
True
>>> isinstance(g, Iterator)
True
>>>
# 因此這裏g是生成器屬於惰性計算序列,因此是Iterator。Iterable && Iterator,可以用for或next迭代
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>>
# 集合數據類型list、dict、str是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象
>>> isinstance('abcd', Iterator)
False
>>> isinstance(iter('abcd'), Iterator)
True
>>> res = iter('asdfds')
>>> res
<str_iterator object at 0x7f199963bcf8>
>>> type(res)
<class 'str_iterator'>
>>>