流暢的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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章