Python高級用法總結

Python很棒,它有不少高級用法值得細細思索,學習使用。本文將根據平常使用,總結介紹Python的一組高級特性,包括:列表推導式、迭代器和生成器、裝飾器。python

列表推導(list comprehensions)

場景1:將一個三維列表中全部一維數據爲a的元素合併,組成新的二維列表。緩存

最簡單的方法:新建列表,遍歷原三維列表,判斷一維數據是否爲a,若爲a,則將該元素append至新列表中。
缺點:代碼太繁瑣,對於Python而言,執行速度會變慢不少。
針對場景1,咱們首先應該想到用列表解析式來解決處理,一行代碼便可解決:app

lista = [item for item in array if item[0] == 'a']

那麼,何爲列表解析式?
官方解釋:列表解析式是Python內置的很是簡單強大的能夠用來建立list的生成式。
強大具體如何體現?
能夠看到,使用列表解析式的寫法更加簡短,除此以外,由於是Python內置的用法,底層使用C語言實現,相較於編寫Python代碼而言,運行速度更快。函數

場景2: 對於一個列表,既要遍歷索引又要遍歷元素。性能

這裏可使用Python內建函數enumerate,在循環中更好的獲取得到索引。學習

array = ['I', 'love', 'Python']
for i, element in enumerate(array):
    array[i] = '%d: %s' % (i, seq[i])

可使用列表推導式對其進行重構:測試

def getitem(index, element):
    return '%d: %s' % (index, element)

array = ['I', 'love', 'Python']
arrayIndex = [getitem(index, element) for index, element in enumerate(array)]

聽說這種寫法更加的Pythonic。大數據

總結:若是要對現有的可迭代對象作一些處理,而後生成新的列表,使用列表推導式將是最便捷的方法。設計

迭代器和生成器

迭代器(Iterator)

這裏的迭代能夠指for循環,在Python中,對於像list,dict和文件等而言,均可以使用for循環,可是它們並非迭代器,它們屬於可迭代對象。
什麼可迭代對象
最簡單的解釋:可使用for...in...語句進行循環的對象,就是可迭代對象(Iterable),可使用isinstance()方法進行判斷。日誌

from collections import Iterable 
type = isinstance('python', Iterable)
print type

什麼是迭代器
迭代器指的是可使用next()方法來回調的對象,能夠對可迭代對象使用iter()方法,將其轉換爲迭代器。

temp = iter([1, 2, 3])
print type(temp)
print next(temp)

此時temp就是一個迭代器。因此說,迭代器基於兩個方法:

  • next:返回下一個項目
  • iter 返回迭代器自己

可理解爲可被next()函數調用並不斷返回下一個值的對象就是迭代器,在定義一個裝飾器時將須要同時定義這兩個方法。

迭代器的優點

在構建迭代器時,不是將全部的元素一次性的加載,而是等調用next方法時返回元素,因此不須要考慮內存的問題。
迭代器應用場景

那麼,具體在什麼場景下可使用迭代器呢?

  • 數列的數據規模巨大
  • 數列有規律,可是不能使用列表推導式描述。

生成器

生成器是一種高級迭代器,使得須要返回一系列元素的函數所需的代碼更加的簡單和高效(不像建立迭代器代碼那般冗長)。
生成器函數
生成器函數基於yield指令,能夠暫停一個函數並返回中間結果。當須要一個將返回一個序列或在循環中執行的函數時,就可使用生成器,由於當這些元素被傳遞到另外一個函數中進行後續處理時,一次返回一個元素能夠有效的提高總體性能。
常見的應用場景是使用生成器的流數據緩衝區。

生成器表達式
生成式表達式是一種實現生成器的便捷方式,將列表推導式的中括號替換爲圓括號。
和列表推導式的區別:列表生成式能夠直接建立一個表,可是生成器表達式是一種邊循環邊計算,使得列表的元素能夠在循環過程當中一個個的推算出來,不須要建立完整的列表,從而節省了大量的空間。

g = (x * x for x in range(10))

總結:生成器是一種高級迭代器。生成器的優勢是延遲計算,一次返回一個結果,這樣很是適用於大數據量的計算。可是,使用生成器必需要注意的一點是:生成器只能遍歷一次。

lambda表達式(匿名函數)

lambda表達式純粹是爲了編寫簡單函數而設計,起到了一個函數速寫的做用,使得簡單函數能夠更加簡潔的表示。
lambda和def的區別
lambda表達式能夠省去定義函數的過程,讓代碼更加的簡潔,適用於簡單函數,編寫處理更大業務的函數須要使用def定義。
lambda表達式常搭配map(), reduce(), filter()函數使用

  • map(): map函數接受兩個參數,一個是函數,一個是序列,其中,函數能夠接收一個或者多個參數。map將傳入的函數依次做用於序列中的每一個元素,將結果做爲新的列表返回。
#將一個列表中的數字轉換爲字符串
map(str, [1,2,3,4,5,6])
  • reduce():函數接收兩個參數,一個是函數,另外一個是序列,可是,函數必須接收兩個參數reduce把結果繼續和序列的下一個元素作累積計算,其效果就是reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)。

  • filter():該函數用於篩選,將傳入的函數,依次做用於每一個元素,而後根據函數的返回值是True仍是False,決定是留下仍是丟棄該元素。

裝飾器

裝飾器本質是一個Python函數,它可讓其它函數在沒有任何代碼變更的狀況下增長額外功能。有了裝飾器,咱們能夠抽離出大量和函數功能自己無關的雷同代碼並繼續重用。常常用於具備切面需求的場景:包括插入日誌、性能測試、事務處理、緩存和權限校驗等。
那麼爲何要引入裝飾器呢?

場景:計算一個函數的執行時間。

一種方法就是定義一個函數,用來專門計算函數的運行時間,而後運行時間計算完成以後再處理真正的業務代碼,代碼以下:

import time 

def get_time(func):
    startTime = time.time()
    func()
    endTime = time.time()
    processTime = (endTime - startTime) * 1000
    print "The function timing is %f ms" %processTime

def myfunc():
    print "start func"
    time.sleep(0.8)
    print "end func"

get_time(myfunc)
myfunc()

可是這段代碼的邏輯破壞了原有的代碼邏輯,就是對全部func函數的調用都須要使用get_time(func)來實現。
那麼,有沒有更好的展現方式呢?固然有,那就是裝飾器。
編寫簡單裝飾器
結合上述實例,編寫裝飾器:

def get_time(func):
    def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        processTime = (endTime - startTime) * 1000
        print "The function timing is %f ms" %processTime
    return wrapper
    
print "myfunc is:", myfunc.__name__
myfunc = get_time(myfunc)
print "myfunc is: ", myfunc.__name__
myfunc()

這樣,一個簡單的完整的裝飾器就實現了,能夠看到,裝飾器並無影響函數的執行邏輯和調用。
在Python中,可使用"@"語法糖來精簡裝飾器的代碼,將上例更改成:

@ get_time
def myfunc():
    print "start func"
    time.sleep(0.8)
    print "end func"

print "myfunc is: ", myfunc.__name__
myfunc()

** 裝飾器的調用順序**
裝飾器能夠疊加使用,若多個裝飾器同時裝飾一個函數,那麼裝飾器的調用順序和@語法糖的聲明順序相反,也就是:

@decorator1
@decorator2
def func():
    pass

等效於:

func = decorator1(decorator2(func()))

被裝飾的函數帶參數
上述實例中,myfunc()是沒有參數的,那若是添加參數的話,裝飾器該如何編寫呢?

#被裝飾的函數帶參數
def get_time3(func):
    def wrapper(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        processTime = (endTime - startTime) * 1000
        print "The function timing is %f ms" %processTime
    return wrapper
@ get_time3
def myfunc2(a):
    print "start func"
    print a
    time.sleep(0.8)
    print "end func"

a = "test"
myfunc2(a)

帶參數的裝飾器
裝飾器有很大的靈活性,它自己支持參數,例如在上述實例中,@get_time裝飾器惟一的參數就是執行業務的函數,固然也能夠在裝飾器中添加參數,加以邏輯判斷。

內置裝飾器

Python中,常見的類裝飾器包括:@staticmathod、@classmethod和@property

  • @staticmethod:類的靜態方法,跟成員方法的區別是沒有self參數,而且能夠在類不進行實例化的狀況下調用。
  • @classmethod:跟成員方法的區別是接收的第一個參數不是self,而是cls(當前類的具體類型)
  • @property:表示能夠直接經過類實例直接訪問的信息。

以上,是本次整理的Python高級用法,本文將持續更新。

相關文章
相關標籤/搜索