generator 生成器python
iterator 迭代器django
collection 集合編程
pack/unpack 打包/解包json
decorator 裝飾器flask
context manager 上下文管理器緩存
python語言的一些高階用法主要有如下幾個特性:數據結構
generators生成器用法app
collections包常見用法socket
itertools包常見用法ide
packing/unpacking封包/解包特性
Decorators裝飾器
Context Managers上下文管理期
以上幾個特性我會針對應用場景,使用注意事項,應用舉例幾個維度分別進行講解,若是有同窗對某個特性特別熟悉則能夠直接跳過。
generator通常用來產生序列類型的值得對象,通常均可以在for循環中迭代,也能夠經過next方法調用,生成器能夠經過yield關鍵字產生。
生成器的做用:
減小內存佔用
好比:利用迭代器的使用方式打開文件
with open("/path/to/file") as f: for line in f: # 這個地方迭代文件 print(line)
提升運行效率
延遲運行,僅當須要運行的地方纔開始執行
以下例子:
def fibonacci_generator(): a, b = 0, 1 while True: yield a a, b = b, a + b # Print all the numbers of the Fibonacci sequence that are lower than 1000 for i in fibonacci_generator(): if i > 1000: break print(i)
輸出結果
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
在python中可使用生成器表達式去迭代一個對象,生成器表達式和列表最大的差異就在因而否一次性將結果計算完成,舉例以下:
a = (x * x for x in range(100)) # a is a generator object print(type(a)) # Sum all the numbers of the generator print(sum(a)) # There are no elements left in the generator print(sum(a))
輸出結果以下:
<class 'generator'> 328350 0
collections包是標準庫的一個模塊,主要目的是用來擴展容器相關的數據類型,
咱們經過dir查看collections包有哪些模塊:
>>> import collections >>> dir(collections) ['Callable', 'Container', 'Counter', 'Hashable', 'ItemsView', 'Iterable', 'Iterator', 'KeysView', 'Mapping', 'MappingView', 'MutableMapping', 'MutableSequence', 'MutableSet', 'OrderedDict', 'Sequence', 'Set', 'Sized', 'ValuesView', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_abcoll', '_chain', '_class_template', '_eq', '_field_template', '_get_ident', '_heapq', '_imap', '_iskeyword', '_itemgetter', '_repeat', '_repr_template', '_starmap', '_sys', 'defaultdict', 'deque', 'namedtuple']
咱們以Counter爲例:
from collections import Counter a = Counter('blue') b = Counter('yellow') print(a) print(b) print((a + b).most_common(3))
輸出結果以下:
Counter({'u': 1, 'e': 1, 'l': 1, 'b': 1}) Counter({'l': 2, 'y': 1, 'e': 1, 'o': 1, 'w': 1}) [('l', 3), ('e', 2), ('y', 1)]
另外defaultdict也是我經常使用的一個模塊,defaultdict是dict的子類,容許咱們經過工廠方法來動態建立不存在的屬性,舉例以下:
from collections import defaultdict my_dict = defaultdict(lambda: 'Default Value') my_dict['a'] = 42 print(my_dict['a']) print(my_dict['b'])
運行結果以下:
42 Default Value
在工做中我常常用defaultdict來構造一顆樹形數據結構來知足個人常規需求,實例以下:
from collections import defaultdict import json def tree(): """ Factory that creates a defaultdict that also uses this factory """ return defaultdict(tree) root = tree() root['Page']['Python']['defaultdict']['Title'] = 'Using defaultdict' root['Page']['Python']['defaultdict']['Subtitle'] = 'Create a tree' root['Page']['Java'] = None print(json.dumps(root, indent=4))
運行結果以下:
{ "Page": { "Python": { "defaultdict": { "Subtitle": "Create a tree", "Title": "Using defaultdict" } }, "Java": null } }
itertools包也是標準庫的一個模塊,他常見的用法是用來擴展迭代器的使用,高效的執行迭代
咱們經過dir方法來查看itertools都有哪些模塊
>>> import itertools >>> dir(itertools) ['__doc__', '__file__', '__name__', '__package__', 'chain', 'combinations', 'combinations_with_replacement', 'compress', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter', 'ifilterfalse', 'imap', 'islice', 'izip', 'izip_longest', 'permutations', 'product', 'repeat', 'starmap', 'takewhile', 'tee']
咱們以permutations舉例以下:
from itertools import permutations for p in permutations([1,2,3]): print(p)
輸出結果:
(1, 2, 3) (1, 3, 2) (2, 1, 3) (2, 3, 1) (3, 1, 2) (3, 2, 1)
combinations示例以下:
from itertools import combinations for c in combinations([1, 2, 3, 4], 2): print(c)
輸出結果:
(1, 2) (1, 3) (1, 4) (2, 3) (2, 4) (3, 4)
另外chain模塊也是經常使用模塊之一
chain使用示例:
from itertools import chain for c in chain(range(3), range(12, 15)): print(c)
輸出結果以下:
0 1 2 12 13 14
另外itertools工具包裏還有不少常見的用法,這裏再也不一一舉例,你們能夠自行嘗試。
在函數參數裏使用*args,**kwargs
都很常見,可是如下的幾種用法大家有試過嗎?
a, *b, c = [2, 7, 5, 6, 3, 4, 1] print(a) print(b) print(c)
以上代碼輸出:
2 [7, 5, 6, 3, 4] 1
有同窗抱怨說這樣運行不對,會報錯,呵呵,那是由於你用的python2,python3中已經對pack,unpack特性進行了很好的實現。
剛纔我已經看到了pack的舉例,咱們接下來再看看unpack
def repeat(count, name): for i in range(count): print(name) print("Call function repeat using a list of arguments:") args = [4, "cats"] repeat(*args) print("Call function repeat using a dictionary of keyword arguments:") args2 = {'count': 4, 'name': 'cats'} repeat(**args2)
運行結果以下:
Call function repeat using a list of arguments: cats cats cats cats Call function repeat using a dictionary of keyword arguments: cats cats cats cats
最後咱們再回歸到函數參數的例子上:
def f(*args, **kwargs): print("Arguments: ", args) print("Keyword arguments: ", kwargs) f(3, 4, 9, foo=42, bar=7)
以上代碼輸出:
Arguments: (3, 4, 9) Keyword arguments: {'bar': 7, 'foo': 42}
裝飾器這個語法糖相信使用flask或者bottle的同窗應該都不陌生,使用django的也應該常常會遇到,可是你們有沒有去想過這個語法糖的應用場景呢?我簡單整理了下,大概有如下幾種裝飾器:
緩存裝飾器
權限驗證裝飾器
計時裝飾器
日誌裝飾器
路由裝飾器
異常處理裝飾器
錯誤重試裝飾器
咱們拿緩存裝飾器舉例:
def cache(function): cached_values = {} # Contains already computed values def wrapping_function(*args): if args not in cached_values: # Call the function only if we haven't already done it for those parameters cached_values[args] = function(*args) return cached_values[args] return wrapping_function @cache def fibonacci(n): print('calling fibonacci(%d)' % n) if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) print([fibonacci(n) for n in range(1, 9)])
以上代碼輸出:
calling fibonacci(1) calling fibonacci(2) calling fibonacci(0) calling fibonacci(3) calling fibonacci(4) calling fibonacci(5) calling fibonacci(6) calling fibonacci(7) calling fibonacci(8) [1, 1, 2, 3, 5, 8, 13, 21]
在python3中有一個包叫作lrucache,就是用的裝飾器的語法糖進行實現。
lrucache的簡單實用以下:
from functools import lru_cache @lru_cache(maxsize=None) def fibonacci(n): print('calling fibonacci(%d)' % n) if n < 2: return n return fibonacci(n-1) + fibonacci(n-2) print([fibonacci(n) for n in range(1, 9)])
運行結果:
calling fibonacci(1) calling fibonacci(2) calling fibonacci(0) calling fibonacci(3) calling fibonacci(4) calling fibonacci(5) calling fibonacci(6) calling fibonacci(7) calling fibonacci(8) [1, 1, 2, 3, 5, 8, 13, 21]
最後咱們再看python中的上下文管理器,這個語法糖在資源管理上有很常見的使用場景,好比上文中我用with open("file") as
的用法,使用了with後就不用擔憂文件不會關閉了,在處理socket編程的時候也能夠用。這個語法糖其實也不難就是兩個魔術方法的實現,__enter__ 和 __exit__,一個控制入口,一個控制出口。
常規的使用with來統計一段代碼運行時間的例子:
from time import time class Timer(): def __init__(self, message): self.message = message def __enter__(self): self.start = time() return None # could return anything, to be used like this: with Timer("Message") as value: def __exit__(self, type, value, traceback): elapsed_time = (time() - self.start) * 1000 print(self.message.format(elapsed_time)) with Timer("Elapsed time to compute some prime numbers: {}ms"): primes = [] for x in range(2, 500): if not any(x % p == 0 for p in primes): primes.append(x) print("Primes: {}".format(primes))
輸出結果:
Primes: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499] Elapsed time to compute some prime numbers: 1.055002212524414ms
其實python是一門特別人性化的語言,但凡在工程中常常遇到的問題,處理起來比較棘手的模式基本都有對應的比較優雅的解決方案。有些寫Java同窗寫python代碼常常看起來像是寫C,沒有一點python語言的影子,所以簡單整理了下python進階的一些用法,但願可以幫助一些同窗。
PS:你們若是轉載請保留出處和做者
PS:若是但願收到本人更多的技術筆記歡迎關注本公共號或者搜索CodingFutuer進行關注