[Python] 03 - Lists, Dictionaries, Tuples, Set

高性能考點


1、高性能編程

高性能測量

查看內存佔用

import sys
sys.getsizeof([1,2,3])

  

耗時對比

In [1]: %timeit l = [1,2,3,4,5,6,7,8,9,0]                                       
58.1 ns ± 1.42 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

In [2]: %timeit l = (1,2,3,4,5,6,7,8,9,0)                                       
9.78 ns ± 0.114 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)

  

高性能原理

算法策略

Dict 原理:[Algorithm] Hashing for searchhtml

Bisect 模塊:一個有趣的python排序模塊:bisectpython

Tim 排序:[Algorithm] Sort for Fun!算法

 

 

2、List Comprehensions

多列表處理

一來效率高;二來支持多列表。注意,解開」嵌套「的順序。編程

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)

 

多條件設置

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered
= [[x for x in row if x % 3 == 0] for row in matrix if sum(row) >= 10]
print(filtered)
>>> [[6], [9]]

 

 

 

 

List 列表 


1、基礎知識 

基礎功能

初始化方法

特例:初始化字符串api

>>> sList = list("hello") >>> sList ['h', 'e', 'l', 'l', 'o']

 

功能函數

append   # 添加一個元素
pop      # 拿走一個元素
sort
reverse
In [11]: dir(list)
Out[11]: 
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']
dir(list)

 

強引用 & 弱應用

弱引用

與apend的區別是:extend只做用於List。app

>>> L = [1, 2]
>>> M = L
>>> L += [3, 4]    # 仍是原來的對象,只是變大了
>>> L, M           # M sees the in-place change too!
([1, 2, 3, 4], [1, 2, 3, 4])

 

強引用 --> 複製

>>> L = [1, 2]
>>> M = L          # L and M reference the same object
>>> L = L + [3, 4] # 實際上是新對象
>>> L, M           # Changes L but not M
([1, 2, 3, 4], [1, 2])

 

強引用 --> [ : ] 表明了 ‘拷貝’

第一個變了;第二個沒變,覺得 [:] 表明了‘拷貝’ 的意思。ssh

 

經過地址查看ide

 

 

2、元素遍歷

是否迭代

 

>>> from collections import Iterable

>>> isinstance('abc', Iterable) # str是否可迭代
True

>>> isinstance([1,2,3], Iterable) # list是否可迭代
True

>>> isinstance(123, Iterable) # 整數是否可迭代
False

 

 

直接遍歷

For 循環

[ 某行第一個元素 for 某行 in 矩陣 ]函數

提取其中一列columnoop

>>> col2 = [row[1] for row in M]   # Collect the items in column 2
>>> col2 [2, 5, 8] >>> M   # The matrix is unchanged [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

>>> [row[1] for row in M if row[1] % 2 == 0]   # Filter out odd items [2, 8]

有點pipeline的意思

>>> [[x ** 2, x ** 3] for x in range(4)] # Multiple values, "if" filters
[[0, 0], [1, 1], [4, 8], [9, 27]]
>>> [[x, x / 2, x * 2] for x in range(−6, 7, 2) if x > 0] [[2, 1, 4], [4, 2, 8], [6, 3, 12]]

 

map - lambda 遍歷

map() 會根據提供的函數對"指定序列"作映射。

map(function, iterable, ...)
# 1. 獨立函數
>>>def square(x) : # 計算平方數 ... return x ** 2 ... >>> map(square, [1,2,3,4,5]) # 計算列表和:1+2+3+4+5 [1, 4, 9, 16, 25]

----------------------------------------------------------------
# 2. 匿名函數 >>> map(lambda x: x ** 2, [1, 2, 3, 4, 5]) # 使用 lambda 匿名函數 [1, 4, 9, 16, 25]
---------------------------------------------------------------- # 3. 提供了兩個列表,對相同位置的列表數據進行相加 >>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]) [3, 7, 11, 15, 19]

Jeff: "第三個也是相對於 for 而言的一個優點"

  

間歇遍歷

next 與 for 循環

計算後獲得若干離散值。

少了 "index定位" 這樣的事情。

In [13]: M = [[1, 2, 3], # A 3 × 3 matrix, as nested lists
    ...: 
    ...: [4, 5, 6], # Code can span lines if bracketed
    ...: 
    ...: [7, 8, 9]]

In [
14]: G = (sum(row) for row in M) # <---- In [16]: next(G)  # 輸出一行 Out[16]: 6 In [17]: next(G)  # 再輸出一行 Out[17]: 15 In [18]: next(G)  # 再輸出一行 Out[18]: 24 

列表(方括號)集合(大括號)字典(大括號)元組(圓括號) 效果對比:

 

generator 生成器

直接自定義了若干離散值。

yield x: Generator function send protocol

From: https://www.jianshu.com/p/d09778f4e055

帶有 yield 的函數再也不是一個普通函數,而是一個生成器generator,可用於迭代,工做原理同next()。

相似 return 的關鍵字。

send(msg)與next()的區別在於send能夠傳遞參數給yield表達式,這時傳遞的參數會做爲yield表達式的值,而yield的參數是返回給調用者的值。

 

其實就是讓一個函數分步執行:

>>> def get_0_1_2():
...   yield 0 ... yield 1 ... yield 2 ... >>> get_0_1_2 <function get_0_1_2 at 0x00B2CB70> 

>>> generator.next()
 
  generator = get_0_1_2()    # 綁定了函數後就開始執行
 
>>> generator.next()
0
>>> generator.next() 1 >>> generator.next() 2 

api有了稍許變化!【這個貌似好用】

generator = get_0_1_2()  # 必須這麼綁定一下,直接用函數名不行

In [83]: next(generator) Out[83]: 0 In [84]: next(generator) Out[84]: 1 In [85]: next(generator) Out[85]: 2 In [86]: next(generator)
Error.

 

 

3、排序

內部方法

改變了本身自己。

>>> L = ['abc', 'ABD', 'aBe'] >>> L.sort()                            # Sort with mixed case
>>> L ['ABD', 'aBe', 'abc']
>>> L = ['abc', 'ABD', 'aBe'] >>> L.sort(key=str.lower) # Normalize to lowercase 忽略大小寫 >>> L ['abc', 'ABD', 'aBe'] >>> L = ['abc', 'ABD', 'aBe'] >>> L.sort(key=str.lower, reverse=True) # Change sort order 反過來 >>> L ['aBe', 'ABD', 'abc']

 

系統方法

生成了新的列表。

>>> L = ['abc', 'ABD', 'aBe'] >>> sorted(L, key=str.lower, reverse=True) # Sorting built-in
['aBe', 'ABD', 'abc']
>>> L = ['abc', 'ABD', 'aBe'] >>> sorted([x.lower() for x in L], reverse=True) # Pretransform items: differs! ['abe', 'abd', 'abc']

 

 

 

Dictionaries 字典


1、初始化的幾種方式

(1) 顯式初始化

>>> D = {'spam': 2, 'ham': 1, 'eggs': 3}      # 顯式初始化
>>> bob1 = dict(name='Bob', job='dev', age=40)     # 參數初始化
>>> bob1
{'age': 40, 'name': 'Bob', 'job': 'dev'}

 

(2) 只有key值

-----------------------------------------------------------------------
------------------------------ 數字 -----------------------------------
-----------------------------------------------------------------------
>>> D = dict.fromkeys(['a', 'b', 'c'], 0) # Initialize dict from keys >>> D {'b': 0, 'c': 0, 'a': 0}

-----------------------------------------------------------------------
>>> D = {k:0 for k in ['a', 'b', 'c']} # Same, but with a comprehension >>> D {'b': 0, 'c': 0, 'a': 0}


-----------------------------------------------------------------------
------------------------------ 字符串 ----------------------------------
-----------------------------------------------------------------------
>>> D = dict.fromkeys('spam') # Other iterables, default value >>> D {'s': None, 'p': None, 'a': None, 'm': None}

-----------------------------------------------------------------------
>>> D = {k: None for k in 'spam'} >>> D {'s': None, 'p': None, 'a': None, 'm': None}

 

(3) key, value 都知道

>>> bob2 = dict( zip(['name', 'job', 'age'], ['Bob', 'dev', 40]) ) # Zipping
>>> bob2
{'job': 'dev', 'name': 'Bob', 'age': 40}

zip的中間過程展現:

>>> list( zip(['a', 'b', 'c'], [1, 2, 3]) ) # Zip together keys and values
[('a', 1), ('b', 2), ('c', 3)]
>>> D = dict( zip(['a', 'b', 'c'], [1, 2, 3]) ) # Make a dict from zip result >>> D {'b': 2, 'c': 3, 'a': 1}

# 進一步,在配對的過程當中能夠作一些lamdb的操做

  >>> D = {k: v for (k, v) in zip(['a', 'b', 'c'], [1, 2, 3])}
  >>> D
  {'b': 2, 'c': 3, 'a': 1}

zip的相反操做 單星號,以下:

>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包爲元組的列表 [(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素個數與最短的列表一致 [(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 與 zip 相反,*zipped 可理解爲解壓,返回二維矩陣式 [(1, 2, 3), (4, 5, 6)]

 

 

 

2、插入操做

單元素添加

a = {‘age’: 23, ‘name’: ‘lala}
a[school] = ‘nanhaizhongxue’

print a
>>> {‘age’: 23, ‘name’: ‘lala’, ‘school’: ‘nanhaizhongxue’} 

 

字典合併

>>> D {'eggs': 3, 'spam': 2, 'ham': 1}
>>> D2 = {'toast':4, 'muffin':5} # Lots of delicious scrambled order here
>>> D.update(D2) >>> D {'eggs': 3, 'muffin': 5, 'toast': 4, 'spam': 2, 'ham': 1}

  

 

3、遍歷鍵值

間接遍歷

單獨輸出全部的key;單獨輸出全部的value;單獨輸出全部的(key, value);

print(dic.keys()) # dict_keys(['趙四', '劉能', '王木生']) 像列表. 山寨列表
for k in dic.keys(): # 拿到的是字典中的每個key
    print(k)
 
print(dic.values()) # dict_values(['劉曉光', '王曉利', '範偉']) 全部的value的一個數據集 for v in dic.values(): print(v)
print(dic.items()) # 全部的鍵值對 dict_items([('趙四', '劉曉光'), ('劉能', '王曉利'), ('王木生', '範偉')]) for k, v in dic.items(): # 遍歷字典最簡單的方案 print(item) # ('趙四', '劉曉光') k, v = item # 解構 k = item[0] v = item[1] print(k, v)

 

直接遍歷

默認的是直接遍歷key值。

dic = {"趙四":"劉曉光", "劉能":"王曉利", "王木生":"範偉"}
# 直接for循環
for key in dic: # 直接循環字典拿到的是key, 有key直接拿value
    print(key)
    print(dic[key])

 

獲取 value 的第二種方式

#!/usr/bin/python  dict = {'Name': 'Zara', 'Age': 27} print "Value : %s" % dict.get('Age') print "Value : %s" % dict.get('Sex', "Never")

 

 

4、排序

排序key值

先取出key值,再排序。

>>> Ks = list( D.keys() ) # Unordered keys list
>>> Ks # A list in 2.X, "view" in 3.X: use list()
['a', 'c', 'b']
>>> Ks.sort() # Sorted keys list >>> Ks ['a', 'b', 'c']
>>> for key in Ks: # Iterate though sorted keys print(key, '=>', D[key]) # <== press Enter twice here (3.X print) a => 1 b => 2 c => 3

 

排序value值

默認是排序value值。

# 鍵
>>> list( D.items() )
[('eggs', 3), ('spam', 2), ('ham', 1)]

 

 

5、判斷 key 是否存在

有麼?

第一種方法:使用自帶函數實現:

在 python 的字典的屬性方法裏面有一個 has_key() 方法:

#生成一個字典
d = {'name':Tom, 'age':10, 'Tel':110}
#打印返回值 print d.has_key('name') #結果返回True

 

在裏面麼?

第二種方法:使用 in 方法: 【推薦,更快】 

#生成一個字典
d = {'name':'Tom', 'age':10, 'Tel':110} #打印返回值,其中d.keys()是列出字典全部的key,如下兩個結果同樣,返回True
print(‘name’ in d.keys()) print('name' in d) #一個例子:多維數據使用 dict.
>>> if (2, 3, 6) in Matrix: # Check for key before fetch
...   print(Matrix[(2, 3, 6)]) # See Chapters 10 and 12 for if/else
... else: ...   print(0) ... 0

除了使用 in 還能夠使用 not in。

 

異常了麼?

第三種方法:try...except方法:

若是不在,形成錯誤,大不了走except路線。

>>> try: ...   print(Matrix[(2, 3, 6)]) # Try to index
... except KeyError: # Catch and recover
...   print(0) # See Chapters 10 and 34 for try/except
... 0

 

 

6、優化遍歷

map & filter

    • 認識到:數據分析 對 "高效Python programming" 的需求!

 

map & reduce

(1) map

>>> def f(x):
...     return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

(2) reduce 

>>> from functools import reduce
>>> def fn(x, y):
...     return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579

(3) map + reduce

from functools import reduce

DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def str2int(s):
    def fn(x, y):
        return x * 10 + y
    def char2num(s):
        return DIGITS[s]
    return reduce(fn, map(char2num, s))

 

稀疏矩陣

    • 妙,表示稀疏矩陣:Using dictionaries for sparse data structures: Tuple keys
>>> Matrix = {}
>>> Matrix[(2, 3, 4)] = 88
>>> Matrix[(7, 8, 9)] = 99
>>>
>>> X = 2; Y = 3; Z = 4 # ; separates statements: see Chapter 10 這裏更靈活!
>>> Matrix[(X, Y, Z)]
88

 

 

 

Tuples 元組


1、不變性 immutability

攜帶一些比較相似list的性質,但功能較少。

>>> T.index(4) # Tuple methods: 4 appears at offset 3
3
>>> T.count(4) # 4 appears once
1

Why Lists and Tuples?

Frankly, tuples are not generally used as often as lists in practice, but their immutability is the whole point.

If you pass a collection of objects around your program as a list, it can be changed anywhere; if you use a tuple, it cannot.

不變性,可能就是其存在的意義。

 

 

2、tuple歧義

小括號中一個元素

括號()既能夠表示tuple,又能夠表示數學公式中的小括號。

只有一個元素的tuple必須跟着「逗號」

>>> t = (1)
>>> t 1 >>> t = (1,) >>> t (1,)

 

「相對」 不變性

tuple的第一級元素不能變,但控制不了元素內部的「可變」。

>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t ('a', 'b', ['X', 'Y'])

 

 

 

Sets 集合


1、常見集合運算

拆分字符串

>>> X = set('spam')         # Make a set out of a sequence in 2.X and 3.X
>>> Y = {'h', 'a', 'm'}     # Make a set with set literals in 3.X and 2.7
>>> X, Y # A tuple of two sets without parentheses ({'m', 'a', 'p', 's'}, {'m', 'a', 'h'})

 

集合邏輯運算

>>> X & Y   # Intersection
{'m', 'a'}
>>> X | Y # Union {'m', 'h', 'a', 'p', 's'}
>>> X - Y # Difference {'p', 's'}
>>> X > Y # Superset False

 

 

2、集合遍歷

注意,這裏是大括號。

>>> {n ** 2 for n in [1, 2, 3, 4]} # Set comprehensions in 3.X and 2.7
{16, 1, 4, 9}

 

 

3、與List的相互轉化

Goto: Python列表、元組、集合、字典的區別和相互轉換

 

End.

相關文章
相關標籤/搜索