1. 程式人生 > >流暢的python(筆記)

流暢的python(筆記)

流暢的python中有很多奇技淫巧,整本書都在強調如何最大限度地利用Python 標準庫。介紹了很多python的不常用的資料型別、操作、庫等,對於入門python後想要提升對python的認識應該有幫助。目前讀一遍記錄了一些有共鳴的操作:

Python內建序列型別的主要分類:

按可存放的元素型別分為:容器序列和扁平序列

  1. 容器序列,就是什麼都能作為元素往裡放,包括另一個序列。需要注意的是,如果元素是序列型別,那麼存放的往往是引用,需要小心。 常見的容器序列包括:list,tuple,array.array,collections.deque等。
  2. 扁平序列,存放的都是原子級元素,此時存放的是值而不會是引用。 常見的扁平序列包括:str,bytes,bytearray, memoryview, array.array等。

按序列能否被修改分為:可變序列與不可變序列

  1. 可變序列:可以進行增、刪、改等操作的序列,包括list, bytearray, array.array, collections.deque, memoryview等。
  2. 不可變序列:不可進行上述操作的序列,包括tuple, str, bytes等。

字典的變種

標準庫裡collections模組中提供了很多與字典型別相似的變種。

OrderDict: 這個型別在新增鍵的時候,會儲存順序,因此鍵的迭代順序總是一致的

ChainMap: 該型別可以容納數個不同的對映對像,在進行鍵的查詢時,這些物件會被當做一個整體逐個查詢,直到鍵被找到為止

Counter: 這個對映型別會給鍵準備一個整數技術器,每次更行一個鍵的時候都會增加這個計數器,所以這個型別可以用來給散列表物件計數,或者當成多重集來用。

UserDict: 這個類其實就是把標準的dict用Python又寫了一遍。一般用來給程式設計師想要通過繼承dict建立自己的dict時,代替dict使用的。主要是因為直接繼承原生dict會出現bug。

defaultdict:處理找不到的鍵的一個選擇 當某個鍵不在對映裡, 我們也希望也能得到一個預設值. 這就是 defaultdict , 它是 dict 的子類, 並實現了 missing 方法.

dict的實現以及導致的結果

鍵必須是可雜湊的:
一個可雜湊的物件必須滿足以下要求。
    (1) 支援 hash() 函式,並且通過 __hash__() 方法所得到的雜湊值是不變的。
    (2) 支援通過 __eq__() 方法來檢測相等性。
    (3) 若 a == b 為真,則 hash(a) == hash(b) 也為真。
    所有由使用者自定義的物件預設都是可雜湊的,因為它們的雜湊值由 id() 來獲取,而
    且它們都是不相等的。
字典在記憶體上開銷很大(用記憶體換效率)。
    元組取代字典就能節省空間的原因有兩個:
    (1) 避免了散列表所耗費的空間,
    (2) 無需把記錄中欄位的名字在每個元素裡都存一遍。
鍵的查詢很快
鍵的次序取決於新增順序
往字典裡新增新鍵可能會改變已有鍵的順序

set的實現以及導致的結果

結合的元素必須是可雜湊的
集合和消耗記憶體
可以很高效的判斷元素是否存在於某個集合
元素的次序取決於被新增到集合裡的順序
往集合裡新增元素,可能會改變集合裡已有的元素次序

collections.namedtuple 可以用來構建一個帶欄位名的元組和一個有名字的類

建立一個具名元組需要兩個引數,一個是類名,另一個是類的各個欄位的名字。後者 可以是由數個字串組成的可迭代物件,或者是由空格分隔開的欄位名組成的字串。

>>> from collections import namedtuple
>>> City = namedtuple('City', 'name country population coordinates')
>>> tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667)) 
>>> tokyo
City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722,
139.691667))
>>> tokyo.population 
36.933
>>> tokyo.coordinates
(35.689722, 139.691667)
>>> tokyo[1]
'JP'

>>> City = namedtuple('City_Name', 'name country population coordinates')
>>> tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
>>> tokyo
City_Name(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))

當列表不是首選時

  1. 如果我們需要一個只包含數字的列表,那麼 array.array 比 list 更高效。陣列支援所 有跟可變序列有關的操作,包括 .pop、.insert 和 .extend。另外,陣列還提供從檔案 讀取和存入檔案的更快的方法,如 .frombytes 和 .tofile。
  2. set 專為檢查元素是否存在做過優化
  3. memoryview 是一個內建類,它能讓使用者在不復制內容的情況下操作同一個陣列的不同切 片。
  4. 使用NumPy和SciPy提供的高階陣列和矩陣操作
  5. 使用雙向佇列和其他形式的佇列(collections.deque 雙向佇列類、queue類中的 Queue、LifoQueue和PriorityQueue、multiprocessing. Queue、heapq可以把可變序列當作堆佇列或者優先佇列來使用)

Python 格式化輸出

在進行格式化輸出時,%r 與 %s 的區別就好比 repr() 函式處理物件與 str() 函式處理物件的差別。

  • %s -> str(),比較智慧;
  • %r -> repr(),處理較為簡單和直接; 處理一些簡單物件時,二者幾乎沒有差別.

本文重點列舉一些二者的差異化用法:

  1. 處理字串時
>> s = 'world'

>> print('hello %s'%s)
hello world
>> print('hello %r'%s)
hello 'world'

>> str(s)
'world'
>> repr(s)
"'world'"
2. datetime 庫中的 datetime 物件
>> from datetime import datetime 
>> timeinfo = datetime.today()

>> timeinfo
datetime.datetime(2016, 6, 7, 21, 17, 34, 925488)
>> type(timeinfo)
datetime.datetime

>> repr(timeinfo)
'datetime.datetime(2016, 6, 7, 21, 17, 34, 925488)'
>> str(timeinfo)
'2016-06-07 21:17:34.925488'

反彙編函式 python opcode

Python dis 模組支援對Python程式碼進行反彙編, 生成位元組碼指令。

In[1]: def test():
...         x = 1
...         if x < 3:
...             return "yes"
...         else:
...             return "no"

In[2]: dis.dis(test)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)
 
  3           6 LOAD_FAST                0 (x)
              9 LOAD_CONST               2 (3)
             12 COMPARE_OP               0 (<)
             15 POP_JUMP_IF_FALSE       22
 
  4          18 LOAD_CONST               3 ('yes')
             21 RETURN_VALUE        
 
  6     >>   22 LOAD_CONST               4 ('no')
             25 RETURN_VALUE        
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE        

>>> def add(a, b = 0):
...     return a + b
... 
>>> 

>>> dis.dis(add)
  2           0 LOAD_FAST                0 (a)
              2 LOAD_FAST                1 (b)
              4 BINARY_ADD
              6 RETURN_VALUE
>>>

class memoryview(obj)是python的內建類,如果要用memoryview 去引用一個object, 那麼這個object 必須支援buffer protocol, python3 中原生(built-in) 支援buffer protocol的obj有bytes和bytearray,memoryview可以使用不同的方式讀取和操作同一塊記憶體,並且原有的記憶體位元組不會隨意移動。類似於C中的強轉,好處是不會有記憶體拷貝。

例如,使用memoryview修改一個短整型有符號整數陣列的資料。

from array import array
from random import random

numbers = array('h', [-2, -1, 0, 1, 2]) #signed short
memv = memoryview(numbers)      #5個短整型有符號整數的陣列建立一個memoryview
print (len(memv))               #列印長度
print (memv.tolist())           #轉換成列表形式

memv_oct = memv.cast('B')       #記憶體共享 轉換成無符號字元型別
print (memv_oct.tolist())

memv_oct[5] = 4                 #把位置5的位元組賦值成4
print (numbers)                 #因為我們把佔 2 個位元組的整數的高位位元組改成了 4,所以這個有符號整數的值就變成了 1024

輸出如下:

5                       #陣列長度
[-2, -1, 0, 1, 2]       #列表形式顯示
[254, 255, 255, 255, 0, 0, 1, 0, 2, 0]#長度擴大一倍 轉換為無符號字元型別
array('h', [-2, -1, 1024, 1, 2])   #原來的陣列被修改

bytearray是可變(mutable)的位元組序列,相對於Python2中的str,但str是不可變(immutable)的。 在Python3中由於str預設是unicode編碼,所以只有通過bytearray才能按位元組訪問。 下面兩種行為的對比: 簡單點就是,str和bytearray的切片操作會產生新的切片str和bytearry並拷貝資料,使用memoryview之後不會。

python2中的例子

不使用memoryview

a = 'aaaaaa' b = a[:2] # 會產生新的字串

a = bytearray('aaaaaa') b = a[:2] # 會產生新的bytearray b[:2] = 'bb' # 對b的改動不影響a a bytearray(b'aaaaaa') b bytearray(b'bb')

使用memoryview

a = 'aaaaaa' ma = memoryview(a) ma.readonly # 只讀的memoryview True mb = ma[:2] # 不會產生新的字串

a = bytearray('aaaaaa') ma = memoryview(a) ma.readonly # 可寫的memoryview False mb = ma[:2] # 不會會產生新的bytearray mb[:2] = 'bb' # 對mb的改動就是對ma的改動 mb.tobytes() 'bb' ma.tobytes() 'bbaaaa'

Python 中有各種各樣可呼叫的型別,因此判斷置的 callable() 函式:

>>> abs, str, 13
(<built-in function abs>, <class 'str'>, 13)
>>> [callable(obj) for obj in (abs, str, 13)]
[True, True, False]
random.shuffle 打亂序列
>>> import random
>>> a=range(10)
>>> random.shuffle(a)
>>> a
[1, 0, 8, 5, 6, 7, 9, 3, 2, 4]
>>> random.shuffle(a)
>>> a
[7, 5, 6, 2, 1, 8, 9, 0, 3, 4]

vim常用快捷

  • 0 → 數字零,到行頭
  • $ → 到本行行尾
  • a → 在游標後插入
  • o → 在當前行後插入一個新行
  • O → 在當前行前插入一個新行
  • cw → 替換從游標所在位置後到一個單詞結尾的字元
  • . → (小數點) 可以重複上一次的命令
  • NG → 到第 N 行 (注意命令中的G是大寫的,另我一般使用 : N 到第N行,如 :137 到第137行)
  • gg → 到第一行。(相當於1G,或 :1)
  • G → 到最後一行。
  • 在 Insert 模式下,你可以輸入一個詞的開頭,然後按或是,自動補齊功能就出現了…

內建函式

Math
Function    Description
abs()   Returns absolute value of a number
divmod()    Returns quotient and remainder of integer division
max()   Returns the largest of the given arguments or items in an iterable
min()   Returns the smallest of the given arguments or items in an iterable
pow()   Raises a number to a power
round() Rounds a floating-point value
sum()   Sums the items of an iterable

Type Conversion
Function    Description
ascii() Returns a string containing a printable representation of an object
bin()   Converts an integer to a binary string
bool()  Converts an argument to a Boolean value
chr()   Returns string representation of character given by integer argument
complex()   Returns a complex number constructed from arguments
float() Returns a floating-point object constructed from a number or string
hex()   Converts an integer to a hexadecimal string
int()   Returns an integer object constructed from a number or string
oct()   Converts an integer to an octal string
ord()   Returns integer representation of a character
repr()  Returns a string containing a printable representation of an object
str()   Returns a string version of an object
type()  Returns the type of an object or creates a new type object

Iterables and Iterators
Function    Description
all()   Returns True if all elements of an iterable are true
any()   Returns True if any elements of an iterable are true
enumerate() Returns a list of tuples containing indices and values from an iterable
filter()    Filters elements from an iterable
iter()  Returns an iterator object
len()   Returns the length of an object
map()   Applies a function to every item of an iterable
next()  Retrieves the next item from an iterator
range() Generates a range of integer values
reversed()  Returns a reverse iterator
slice() Returns a slice object
sorted()    Returns a sorted list from an iterable
zip()   Creates an iterator that aggregates elements from iterables

Composite Data Type
Function    Description
bytearray() Creates and returns an object of the bytearray class
bytes() Creates and returns a bytes object (similar to bytearray, but immutable)
dict()  Creates a dict object
frozenset() Creates a frozenset object
list()  Constructs a list object
object()    Returns a new featureless object
set()   Creates a set object
tuple() Creates a tuple object

Classes, Attributes, and Inheritance
Function    Description
classmethod()   Returns a class method for a function
delattr()   Deletes an attribute from an object
getattr()   Returns the value of a named attribute of an object
hasattr()   Returns True if an object has a given attribute
isinstance()    Determines whether an object is an instance of a given class
issubclass()    Determines whether a class is a subclass of a given class
property()  Returns a property value of a class
setattr()   Sets the value of a named attribute of an object
super() Returns a proxy object that delegates method calls to a parent or sibling class

Input/Output
Function    Description
format()    Converts a value to a formatted representation
input() Reads input from the console
open()  Opens a file and returns a file object
print() Prints to a text stream or the console

Variables, References, and Scope
Function    Description
dir()   Returns a list of names in current local scope or a list of object attributes
globals()   Returns a dictionary representing the current global symbol table
id()    Returns the identity of an object
locals()    Updates and returns a dictionary representing current local symbol table
vars()  Returns __dict__ attribute for a module, class, or object

Miscellaneous
Function    Description
callable()  Returns True if object appears callable
compile()   Compiles source into a code or AST object
eval()  Evaluates a Python expression
exec()  Implements dynamic execution of Python code
hash()  Returns the hash value of an object
help()  Invokes the built-in help system
memoryview()    Returns a memory view object
staticmethod()  Returns a static method for a function
__import__()    Invoked by the import statement

跟運算子無關的特殊方法

類別 方法名
字串 / 位元組序列表示形式 __repr__、__str__、__format__、__bytes__
數值轉換 __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__
集合模擬 __len__、__getitem__、__setitem__、__delitem__、__contains__
迭代列舉 __iter__、__reversed__、__next__
可呼叫模擬 __call__
上下文管理 __enter__、__exit__
例項建立和銷燬 __new__、__init__、__del__
屬性管理 __getattr__、__getattribute__、__setattr__、__delattr__、__dir__
屬性描述符 __get__、__set__、__delete__
跟類相關的服務 __prepare__、__instancecheck__、__subclasscheck__

Bisect模組管理有序的序列

bisect.bisect_left(a,x, lo=0, hi=len(a)) :
查詢在有序列表 a 中插入 x 的index。lo 和 hi 用於指定列表的區間,預設是使用整個列表。如果 x 已經存在,在其左邊插入。返回值為 index。
bisect.bisect_right(a,x, lo=0, hi=len(a))
bisect.bisect(a, x,lo=0, hi=len(a)) :
這2個函式和 bisect_left 類似,但如果 x 已經存在,在其右邊插入。
bisect.insort_left(a,x, lo=0, hi=len(a)) :
在有序列表 a 中插入 x。和 a.insert(bisect.bisect_left(a,x, lo, hi), x) 的效果相同。
bisect.insort_right(a,x, lo=0, hi=len(a))
bisect.insort(a, x,lo=0, hi=len(a)) :
和 insort_left 類似,但如果 x 已經存在,在其右邊插入。
Bisect 模組提供的函式可以分兩類: bisect* 只用於查詢 index, 不進行實際的插入;而 insort* 則用於實際插入。

當list不是最優選擇時,dict是python的核心型別,但它是以空間換時間的結果,比較佔記憶體,tuple是dict結構比較好的替代,set用來做是否包含和去重很合適。

from array import array  
from random import random
floats = array('d', (random() for i in range(10**7)))  
fp = open('floats.bin', 'wb')
floats.tofile(fp)  
fp.close()
floats2 = array('d')  
fp = open('floats.bin', 'rb')
floats2.fromfile(fp, 10**7)  
fp.close()
floats2 == floats

Python_內建四種佇列

from queue import Queue #LILO佇列
q = Queue() #建立佇列物件
q.put(0)    #在佇列尾部插入元素
q.put(1)
q.put(2)
print('LILO佇列',q.queue)  #檢視佇列中的所有元素
print(q.get())  #返回並刪除佇列頭部元素
print(q.queue)

from queue import LifoQueue #LIFO佇列
lifoQueue = LifoQueue()
lifoQueue.put(1)
lifoQueue.put(2)
lifoQueue.put(3)
print('LIFO佇列',lifoQueue.queue)
lifoQueue.get() #返回並刪除佇列尾部元素
lifoQueue.get()
print(lifoQueue.queue)

from queue import PriorityQueue #優先佇列
priorityQueue = PriorityQueue() #建立優先佇列物件
priorityQueue.put(3)    #插入元素
priorityQueue.put(78)   #插入元素
priorityQueue.put(100)  #插入元素
print(priorityQueue.queue)  #檢視優先順序佇列中的所有元素
priorityQueue.put(1)    #插入元素
priorityQueue.put(2)    #插入元素
print('優先順序佇列:',priorityQueue.queue)  #檢視優先順序佇列中的所有元素
priorityQueue.get() #返回並刪除優先順序最低的元素
print('刪除後剩餘元素',priorityQueue.queue)
priorityQueue.get() #返回並刪除優先順序最低的元素
print('刪除後剩餘元素',priorityQueue.queue)  #刪除後剩餘元素
priorityQueue.get() #返回並刪除優先順序最低的元素
print('刪除後剩餘元素',priorityQueue.queue)  #刪除後剩餘元素
priorityQueue.get() #返回並刪除優先順序最低的元素
print('刪除後剩餘元素',priorityQueue.queue)  #刪除後剩餘元素
priorityQueue.get() #返回並刪除優先順序最低的元素
print('全部被刪除後:',priorityQueue.queue)  #檢視優先順序佇列中的所有元素

from collections import deque   #雙端佇列
dequeQueue = deque(['Eric','John','Smith'])
print(dequeQueue)
dequeQueue.append('Tom')    #在右側插入新元素
dequeQueue.appendleft('Terry')  #在左側插入新元素
print(dequeQueue)
dequeQueue.rotate(2)    #迴圈右移2次
print('迴圈右移2次後的佇列',dequeQueue)
dequeQueue.popleft()    #返回並刪除佇列最左端元素
print('刪除最左端元素後的佇列:',dequeQueue)
dequeQueue.pop()    #返回並刪除佇列最右端元素
print('刪除最右端元素後的佇列:',dequeQueue)


以上佇列在多執行緒中可以使用的且執行緒安全,但在多程序中都不能用於通訊。在多程序中,需要這樣使用:
from multiprocessing import Process, Queue
myqueue = Queue(100)


## 參考

https://blog.csdn.net/sinat_38682860/article/details/80392493 
https://www.cnblogs.com/cmnz/p/6936181.html

關鍵字

from keyword import kwlist
print(kwlist)

builtins模組

import builtins
dir(builtins)