標籤:

python高級特性

名詞與翻譯對照表

  • generator 生成器
  • iterator 迭代器
  • collection 集合
  • pack/unpack 打包/解包
  • decorator 裝飾器
  • context manager 上下文管理器

本篇文章重點介紹以下內容

python語言的一些高階用法主要有以下幾個特性:

  • generators生成器用法
  • collections包常見用法
  • itertools包常見用法
  • packing/unpacking封包/解包特性
  • Decorators裝飾器
  • Context Managers上下文管理期

以上幾個特性我會針對應用場景,使用注意事項,應用舉例幾個維度分別進行講解,如果有同學對某個特性特別熟悉則可以直接跳過。

generators生成器用法

generator一般用來產生序列類型的值得對象,一般都可以在for循環中迭代,也可以通過next方法調用,生成器可以通過yield關鍵字產生。

生成器的作用:

  • 減少內存佔用n比如:利用迭代器的使用方式打開文nwith open("/path/to/file") as f: n for line in f: # 這個地方迭代文件n print(line)
  • 提高運行效率
  • 延遲運行,僅當需要運行的地方才開始執行

如下例子:

def fibonacci_generator():n a, b = 0, 1n while True:n yield an a, b = b, a + bnn# Print all the numbers of the Fibonacci sequence that are lower than 1000nfor i in fibonacci_generator():n if i > 1000:n breakn print(i)n

輸出結果

0n1n1n2n3n5n8n13n21n34n55n89n144n233n377n610n987n

在python中可以使用生成器表達式去迭代一個對象,生成器表達式和列表最大的差別就在於是否一次性將結果計算完成,舉例如下:

a = (x * x for x in range(100))nn# a is a generator objectnprint(type(a))nn# Sum all the numbers of the generatornprint(sum(a))nn# There are no elements left in the generatornprint(sum(a))n

輸出結果如下:

<class generator>n328350n0n

collections包常見用法

collections包是標準庫的一個模塊,主要目的是用來擴展容器相關的數據類型,n我們通過dir查看collections包有哪些模塊:

>>> import collectionsn>>> dir(collections)n[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]n

我們以Counter為例:

from collections import Counternna = Counter(blue)nb = Counter(yellow)nnprint(a)nprint(b)nprint((a + b).most_common(3))n

輸出結果如下:

Counter({u: 1, e: 1, l: 1, b: 1})nCounter({l: 2, y: 1, e: 1, o: 1, w: 1})n[(l, 3), (e, 2), (y, 1)]n

另外defaultdict也是我常用的一個模塊,defaultdict是dict的子類,允許我們通過工廠方法來動態創建不存在的屬性,舉例如下:

from collections import defaultdictnnmy_dict = defaultdict(lambda: Default Value)nmy_dict[a] = 42nnprint(my_dict[a])nprint(my_dict[b])n

運行結果如下:

42nDefault Valuen

在工作中我經常用defaultdict來構造一顆樹形數據結構來滿足我的常規需求,實例如下:

from collections import defaultdictnimport jsonnndef tree():n """n Factory that creates a defaultdict that also uses this factoryn """n return defaultdict(tree)nnroot = tree()nroot[Page][Python][defaultdict][Title] = Using defaultdictnroot[Page][Python][defaultdict][Subtitle] = Create a treenroot[Page][Java] = Nonennprint(json.dumps(root, indent=4))n

運行結果如下:

{n "Page": {n "Python": {n "defaultdict": {n "Subtitle": "Create a tree",n "Title": "Using defaultdict"n }n },n "Java": nulln }n}n

itertools包常見用法

itertools包也是標準庫的一個模塊,他常見的用法是用來擴展迭代器的使用,高效的執行迭代

我們通過dir方法來查看itertools都有哪些模塊

>>> import itertoolsn>>> dir(itertools)n[__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]n

我們以permutations舉例如下:

from itertools import permutationsnnfor p in permutations([1,2,3]):n print(p)n

輸出結果:

(1, 2, 3)n(1, 3, 2)n(2, 1, 3)n(2, 3, 1)n(3, 1, 2)n(3, 2, 1)n

combinations示例如下:

from itertools import combinationsnnfor c in combinations([1, 2, 3, 4], 2):n print(c)n

輸出結果:

(1, 2)n(1, 3)n(1, 4)n(2, 3)n(2, 4)n(3, 4)n

另外chain模塊也是常用模塊之一nchain使用示例:

from itertools import chainnnfor c in chain(range(3), range(12, 15)):n print(c)n

輸出結果如下:

0n1n2n12n13n14n

另外itertools工具包里還有很多常見的用法,這裡不再一一舉例,大家可以自行嘗試。

packing/unpacking特性

在函數參數里使用*args,**kwargs都很常見,但是以下的幾種用法你們有試過嗎?

a, *b, c = [2, 7, 5, 6, 3, 4, 1]nprint(a)nprint(b)nprint(c)n

以上代碼輸出:

2n[7, 5, 6, 3, 4]n1n

有同學抱怨說這樣運行不對,會報錯,呵呵,那是因為你用的python2,python3中已經對pack,unpack特性進行了很好的實現。

剛才我已經看到了pack的舉例,我們接下來再看看unpack

def repeat(count, name):n for i in range(count):n print(name)nnprint("Call function repeat using a list of arguments:")nargs = [4, "cats"]nrepeat(*args)nnprint("Call function repeat using a dictionary of keyword arguments:")nargs2 = {count: 4, name: cats}nrepeat(**args2)n

運行結果如下:

Call function repeat using a list of arguments:ncatsncatsncatsncatsnCall function repeat using a dictionary of keyword arguments:ncatsncatsncatsncatsn

最後我們再回歸到函數參數的例子上:

def f(*args, **kwargs):n print("Arguments: ", args)n print("Keyword arguments: ", kwargs)nnf(3, 4, 9, foo=42, bar=7)n

以上代碼輸出:

Arguments: (3, 4, 9)nKeyword arguments: {bar: 7, foo: 42}n

Decorators裝飾器

裝飾器這個語法糖相信使用flask或者bottle的同學應該都不陌生,使用django的也應該經常會遇到,但是大家有沒有去想過這個語法糖的應用場景呢?我簡單整理了下,大概有以下幾種裝飾器:

  • 緩存裝飾器
  • 許可權驗證裝飾器
  • 計時裝飾器
  • 日誌裝飾器
  • 路由裝飾器
  • 異常處理裝飾器
  • 錯誤重試裝飾器

我們拿緩存裝飾器舉例:

def cache(function):n cached_values = {} # Contains already computed valuesn def wrapping_function(*args):n if args not in cached_values:n # Call the function only if we havent already done it for those parametersn cached_values[args] = function(*args)n return cached_values[args]n return wrapping_functionnn@cachendef fibonacci(n):n print(calling fibonacci(%d) % n)n if n < 2:n return nn return fibonacci(n-1) + fibonacci(n-2)nnprint([fibonacci(n) for n in range(1, 9)])n

以上代碼輸出:

calling fibonacci(1)ncalling fibonacci(2)ncalling fibonacci(0)ncalling fibonacci(3)ncalling fibonacci(4)ncalling fibonacci(5)ncalling fibonacci(6)ncalling fibonacci(7)ncalling fibonacci(8)n[1, 1, 2, 3, 5, 8, 13, 21]n

在python3中有一個包叫做lrucache,就是用的裝飾器的語法糖進行實現。

lrucache的簡單實用如下:

from functools import lru_cachenn@lru_cache(maxsize=None)ndef fibonacci(n):n print(calling fibonacci(%d) % n)n if n < 2:n return nn return fibonacci(n-1) + fibonacci(n-2)nnprint([fibonacci(n) for n in range(1, 9)])n

運行結果:

calling fibonacci(1)ncalling fibonacci(2)ncalling fibonacci(0)ncalling fibonacci(3)ncalling fibonacci(4)ncalling fibonacci(5)ncalling fibonacci(6)ncalling fibonacci(7)ncalling fibonacci(8)n[1, 1, 2, 3, 5, 8, 13, 21]n

Context Managers上下文管理期

最後我們再看python中的上下文管理器,這個語法糖在資源管理上有很常見的使用場景,比如上文中我用with open("file") as的用法,使用了with後就不用擔心文件不會關閉了,在處理socket編程的時候也可以用。這個語法糖其實也不難就是兩個魔術方法的實現,enterexit,一個控制入口,一個控制出口。

常規的使用with來統計一段代碼運行時間的例子:

from time import timennnclass Timer():n def __init__(self, message):n self.message = messagenn def __enter__(self):n self.start = time()n return None # could return anything, to be used like this: with Timer("Message") as value:nn def __exit__(self, type, value, traceback):n elapsed_time = (time() - self.start) * 1000n print(self.message.format(elapsed_time))nnnwith Timer("Elapsed time to compute some prime numbers: {}ms"):n primes = []n for x in range(2, 500):n if not any(x % p == 0 for p in primes):n primes.append(x)n print("Primes: {}".format(primes))n

輸出結果:

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]nElapsed time to compute some prime numbers: 1.055002212524414msn

總結

其實python是一門特別人性化的語言,但凡在工程中經常遇到的問題,處理起來比較棘手的模式基本都有對應的比較優雅的解決方案。有些寫Java同學寫python代碼經常看起來像是寫C,沒有一點python語言的影子,因此簡單整理了下python進階的一些用法,希望能夠幫助一些同學。

PS:大家如果轉載請保留出處和作者

PS:如果希望收到本人更多的技術筆記歡迎關注本人微信公共號搜索CodingFutuer進行關注

推薦閱讀:

Python面向對象編程(OOP)
PyQt5系列教程(11):今天的消息挺全哦!
如何系統的自學Python?
給妹子講python--01好用的列表
Python入門 數據結構 dict字典

TAG:Python教程 |