Python高階用法總結


前言: 接觸python有一段時間了,從開始的看菜鳥的python教程,看了一些視頻,一些書。很多人感覺python很簡單,確實相比其他語言,python可能稍微簡單一點,但是不能說只學了python基礎語法就說自己python水平可以了。最近在閱讀YOLOv3的pytorch版本源碼,就遇到很多瓶頸,很多是與python相關的。所以這篇進行總結一下,收集一下所有的問題,更深入理解python高階用法,並且盡量每個都附上例子,做一個認真的coder,bloger。

1. lambda匿名函數

lambda匿名函數在一些工程項目中經常出現,理解該用法是讀懂項目的前提。如:

lf = lambda x: 1 - 10 ** (hyp['lrf'] * (1 - x / epochs)) 

匿名函數就是沒有定義函數的名稱,用來實現簡單的功能。

語法結構:lambda param_list: expression

param_list 就是參數列表,相當於函數的參數

expression 就是表達式,相當於函數體,用一行進行表示

舉個簡單的例子:

>>> func=lambda x, y: x+y
>>> func(3,4)
7

應用場景:

1.1 函數式編程

python提供了很多函數式編程特性,如map, reduce, filter, sorted等內置函數,都支持函數作為參數。

  • map會根據提供的函數對指定序列做映射。

    • map(function, iterable, ...)

    •   >>> func2=lambda x: x**x
        >>> L=[1,2,3]
        >>> map(func2, L)
        <map object at 0x00000218C07F0080>
        >>> list(map(func2, L)) # 注意要顯示內容需要轉為list類型,因為py3中返回的是迭代器對象
        [1, 4, 27]
        >>>
      
    • 其中function可以使lambda函數對象,也可以是str等類型

    •   >>> L=[1,2,3,4]
        >>> list(map(str, L))
        ['1', '2', '3', '4']
        >>> list(map(float, L))
        [1.0, 2.0, 3.0, 4.0]
      
  • reduce 函數會對參數序列中元素進行累積。

    • 語法:reduce(function, iterable[, initializer])

    •   >>> reduce(lambda x, y: x+y, [1,2,3,4,5])  # 使用 lambda 匿名函數
        15
      
    • 注意python3使用前要加上:from functools import reduce , reduce函數在python3中被移除,放入了functools模塊。

  • filter內置函數用於過濾序列,過濾掉不符合條件的元素,返回由符合條件元素組成的新列表。

    •   filter(function, iterable)
      
    •   >>> filter(lambda x: x % 2 == 0, [1,2,3,4,5,6,7,8,9,10])
        <filter object at 0x00000218C07F0080>
        >>> list(filter(lambda x: x % 2 == 0, [1,2,3,4,5,6,7,8,9,10]))
        [2, 4, 6, 8, 10]
        >>>
      
    • 這里function智能返回true or false, 將滿足true的放入最終列表。

  • sorted函數對所有可迭代的對象進行排序操作。

    • sorted(iterable, key=None, reverse=False)

    •   >>> sorted([[3,4],[2,1],[5,3],[7,4],[9,0]], key=lambda x:x[0])
        [[2, 1], [3, 4], [5, 3], [7, 4], [9, 0]]
      

1.2 應用在閉包

def get_y(a,b):
     return lambda x:ax+b
y1 = get_y(1,1)
y1(1) # 結果為2

用常規函數實現閉包,如下:

def get_y(a,b):
    def func(x):
        return ax+b
    return func
y1 = get_y(1,1)
y1(1) # 結果為2

例子轉載自:https://www.cnblogs.com/hf8051/p/8085424.html

2. 列表解析式

列表解析式是Python內置的非常簡單強大的可以用來創建list的生成式。在深度學習項目中也可以經常看到這種用法。

(1) 語法1:[表達式 for 變量 in 列表],表示把得到的每一個變量值都放到 for 前面的表達式中計算 ,然后生成一個列表
(2) 語法2:[表達式 for 變量 in 列表 if 條件],如果加上 if 判斷,則表示把每一個變量值進行判斷,如果判斷正確再交給表達式進行計算,然后生成一個列表

舉例:

>>> items=[1,2,3,4,5,6,7]
>>> [item*2 for item in items]
[2, 4, 6, 8, 10, 12, 14]
>>> [item*2 for item in items if item % 2 == 0]
[4, 8, 12]

使用列表解析式的寫法更加簡短,除此之外,因為是Python內置的用法,底層使用C語言實現,相較於編寫Python代碼而言,運行速度更快。

3. enumerate內建函數

對於一個列表,既要遍歷索引又要遍歷元素。

>>> days=['mon','tus','wed','ths','fri','sat','sun']
>>> for i,day in enumerate(days):
...     print(i,day)
...
0 mon
1 tus
2 wed
3 ths
4 fri
5 sat
6 sun
>>> for i,day in enumerate(days, start=1):
...     print(i,day)
...
1 mon
2 tus
3 wed
4 ths
5 fri
6 sat
7 sun
>>>

4. 迭代器與生成器

有時候項目會使用到這種語法,如果不了解這兩種用法,可能很難讀懂代碼,可能會直接懵B o((⊙﹏⊙))o。下面分別看看這兩個的用法:

4.1 迭代器

迭代器指的是可以使用next()方法來回調的對象,可以對可迭代對象使用iter()方法,將其轉換為迭代器。

>>> L=[1,2,3,4,5]
>>> lst = iter(L)
>>> type(lst)
<class 'list_iterator'>
>>> L1=(1,2,3,4,5)
>>> lst1 = iter(L1)
>>> type(lst1)
<class 'tuple_iterator'>
>>> next(lst)
1
>>> next(lst1)
1
>>>

迭代器優勢: 所有的元素不是一次性加載的,在調用next方法才會返回,不需要考慮內存問題。next()只能往后進行訪問。

迭代器應用場景:

  1. list規模過大,出於對內存的考慮使用迭代器。
  2. 有規律,但是不能使用列表推導式描述

迭代器的創建:

  1. __iter__() 方法返回一個特殊的迭代器對象, 這個迭代器對象實現了 next() 方法並通過 StopIteration 異常標識迭代的完成。
  2. __next__() 方法(Python 2 里是 next())會返回下一個迭代器對象。
class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    x = self.a
    self.a += 1
    return x
 
myclass = MyNumbers()
myiter = iter(myclass)
 
print(next(myiter))
print(next(myiter))

例子來自菜鳥教程:https://www.runoob.com/python3/python3-iterator-generator.html

4.3 生成器

生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。

使用了yield的函數被稱為生成器。

在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回 yield 的值, 並在下一次執行 next() 方法時從當前位置繼續運行。(之前也遇見過yolo的代碼中使用了這種用法,需要仔細理解並掌握)

#!/usr/bin/python3
 
import sys
 
def fibonacci(n): # 生成器函數 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一個迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

例子來自菜鳥教程:https://www.runoob.com/python3/python3-iterator-generator.html

生成器的優點是延遲計算,一次返回一個結果,這樣非常適用於大數據量的計算。但是,使用生成器必須要注意的一點是:生成器只能遍歷一次。

5. 裝飾器

裝飾器本質是一個python函數,如果學過flask就知道,里邊裝飾器是必須的,經常用到。

裝飾器的作用:抽離大量和函數功能本身無關的代碼進行重用

一個簡單的裝飾器,用於計數,由於對不同的函數運行時間進行計數的需要,所以要對時間計數這部分進行處理。

def get_time(func):
	def wrapper():
        startTime = time.time()
        func()
        endTime = time.time()
        print("spend %f" % (endTime-startTime))
    return wrapper
myFunction = get_time(myFunction)
	

精簡一下,使用@語法來進行精簡:

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)
    
@get_time
def myfunc():
	print("start")
	time.sleep(0.8)
	print("end")

if __name__ == "__main__":
    myfunc

output:

start
end
The function timing is 800.058126 ms

理解為:get_time(myfun()) ,將myfunc()函數包裹

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

@decorator1
@decorator2
def func():
    pass

等效於:

func = decorator1(decorator2(func()))

內置裝飾器

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

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

了解更多請看:https://www.jianshu.com/p/ee82b941772a


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM