天天看點

Python:被忽視的核心功能

作者:CSDN
Python:被忽視的核心功能

【編者按】這篇文章主要介紹了一些在 Python 程式設計中可能被忽視的核心功能,包括預設參數、海象運算符、*args 和 **kwargs 的使用、變量交換、str 與 repr 的差別、可疊代對象的擴充解包、多個上下文管理器的使用、Python 調試器、collections.Counter 的使用、itertools 的使用以及下劃線的兩種用法等。

原文連結:https://erikvandeven.medium.com/python-uncovering-the-overlooked-core-functionalities-54590420c225

未經允許,禁止轉載!

作者 | Erik van de Ven 譯者 | 明明如月責編 | 夏萌

出品 | CSDN(ID:CSDNnews)

Python:被忽視的核心功能

圖檔由 Stefan Steinbauer 提供,釋出在 Unsplash 上

Kyle Simpson 在他的書中提到的關于 JavaScript 的觀點,Luciano Ramalho 在他的《Fluent Python》一書中對 Python 的描述也有相同的主題。他們基本上是在讨論這兩種語言的同一個問題。用我的話來說:

因為這門語言非常容易學,許多實踐者隻是了解了它的基礎知識,而忽略了深入探讨這門語言更進階和強大的方面,這也是它真正獨特和強大的地方。

是以,讓我們簡要讨論一下所有你可能還沒有聽說過的功能,但如果你想成為一名真正經驗豐富的 Pythonista,你肯定想了解。

Python:被忽視的核心功能

參數預設值

需要重點注意的是,Python 的參數在遇到函數定義時就進行評估。這意味着每次調用 fib_memo 函數(下文會提到)而沒有明确提供 memo 參數的值時,它将使用函數定義時建立的相同字典對象。

def fib_memo(n, memo={0:0, 1:1}):               """               n 是你想要傳回的序列中的第 n 個數字               """               if not n in memo:               memo[n] = fib_memo(n-1) + fib_memo(n-2)               return memo[n]                  # 傳回一個介于0和100之間(包括0和100)的數字。               fib_memo(6) # 應該傳回8           

這段代碼在 Python 中可以正常運作。這也意味着你可以在一個腳本中多次執行 fib_memo 函數,比如在一個 for 循環中,每次執行都會增加要計算的 fibonacci 數字,而不會達到“超過最大遞歸深度”的限制,因為 memo 會不斷擴充。關于這方面的更多資訊可以在我的另一篇文章中找到。

Python:被忽視的核心功能

海象操作符

海象操作符 (:= ) 是在 Python 3.8 中引入的,它允許你在表達式中為變量指派。這樣,你可以在一個表達式中為變量指派并檢查其值:

import random              some_value = random.randint(0,100) # 傳回一個介于0和100之間(包括0和100)的數字。              if((below_ten := some_value) < 10):               print(f"{below_ten} 小于 10")           

顯然,它也可以友善地指派并檢查傳回的值是否包含真值:

if(result := some_method()): # 如果結果不為假值(Falsy)               print(result)           
Python:被忽視的核心功能

*args 和 **kwargs

通過星号 (* ),你可以在傳遞給函數之前解包參數或關鍵字參數(使用 ** )。

例如,考慮以下代碼:

my_numbers = [1,2]              def sum_numbers(first_number, second_number):               return first_number + second_number                  # 這将傳回一個類型錯誤。              # 類型錯誤:sum() 缺少 1 個必需的位置參數:“second_number” sum_numbers(my_numbers)                  #這将傳回預期的結果,3。              sum_numbers(*my_numbers)           

當我們調用 sum_numbers 函數時,如果不解包 my_numbers,它會引發一個 TypeError ,因為函數期望兩個獨立的參數。然而,通過使用星号 (*),我們可以從 my_numbers 中解包值并将它們作為獨立的參數傳遞,進而得到正确的輸出。

這種解包技術不僅适用于元組和清單,還适用于字典(盡管它會将鍵作為參數傳遞)。那麼關鍵字參數呢?對此,我們可以利用雙星号 (**)。以下代碼作為例子:

def greet_person(last_name, first_name):               print(f"Hello {first_name} {last_name}")                  data = {"first_name": "John", "last_name": "Doe"}              greet_person(**data)           

除了解包一個序列來将它們作為函數的參數,你也可以用它來建立一個新的序列,例如:

numbers = [1, 2, 3, 4, 5]              new_list_numbers = [*numbers]           

原始的 numbers 清單保持不變,而你有一個 new_list_numbers 變量,它包含了相同清單的副本。然而,對于包含對象的連結要小心:

numbers = [[1, 2], [3, 4], [5, 6]]              packed_numbers = [*numbers]                  numbers[0].append(10) # 修改原始清單中的嵌套清單                  print(numbers) # 輸出: [[1, 2, 10], [3, 4], [5, 6]]               print(packed_numbers) # 輸出: [[1, 2, 10], [3, 4], [5, 6]]           
Python:被忽視的核心功能

any 和 all

any 和 all 是兩個内建函數,它們對可疊代對象(如清單、元組或集合)進行操作,并基于可疊代對象中的元素傳回一個布爾值。

例如:

some_booleans = [True, False, False, False]                  any(some_booleans) # 傳回 True              all(some_booleans) # 傳回 False           

你可以将 all 和 any 函數與清單推導式結合使用,它傳回一個可疊代的結果并将其作為參數傳遞給 all 函數:

numbers = [5, 10, 3, 8, -2]              all_positive = all(num > 0 for num in numbers)           

… 或 any 函數:

fruits = ['apple', 'banana', 'cherry', 'durian']                  # 檢查是否所有水果都以“a”開頭              result = all(fruit.startswith('a') for fruit in fruits)              print(result)           

下面的表格顯示了根據可疊代對象中的值傳回的輸出的不同。

Python:被忽視的核心功能
Python:被忽視的核心功能

變量交換

你可以組合元組打包(在等号 (=) 右邊發生)和解包(在等号 (=) 左邊發生),并利用這個功能進行變量交換:

a = 10              b = 5                  # 通過打包和解包交換 b 和 a 的值              a, b = b, a                  print(a) #5              print(b) #10           
Python:被忽視的核心功能

str vs repr

我們習慣于使用 str(some_value) 将某個變量或值轉換為字元串,以便于進行調試列印。我想讓你了解 repr(some_value)。主要的差別是 repr 嘗試傳回對象的可列印表示,而 str 隻嘗試傳回一個字元串表示。

下面是一個更好的例子:

import datetime                  today = datetime.datetime.now()                  print(str(today))print(str(today)) # 輸出: 2023-07-20 15:30:00.123456              print(repr(today)) # 輸出:datetime.datetime(2023, 7, 20, 15, 30, 0, 123456)           

如你所見,str() 簡單地将 datetime 作為一個字元串表示傳回。如果你想确定變量 today 是否包含一個字元串還是一個 datetime 對象,你無法單獨從這個資訊中得到答案。另一方面,repr() 提供了有關變量所持有的實際對象的資訊。在調試過程中,這個資訊會更有價值。

Python:被忽視的核心功能

擴充的可疊代對象解包

這個可以簡單了解:如果你想通過一個指令擷取序列的第一個和最後一個值:

first, *middle, last = [1, 2, 3, 4, 5]                  print(first) # 1              print(middle) # [2, 3, 4]              print(last) # 5           

但這也是可行的

*the_first_three, second_last, last = [1, 2, 3, 4, 5]                  print(the_first_three) # [1, 2, 3]              print(second_last) # 4              print(last) # 5           

或者其他組合。

Python:被忽視的核心功能

多個上下文管理器

我們習慣于一次使用一個上下文管理器,比如打開一個檔案:

with open('file.txt', 'r') as file:              # 使用該檔案的代碼              # 該檔案将在塊結束時自動關閉              # 即使發生異常                  # 示例:從檔案中讀取行              for line in file:              print(line.strip())                  with open('file_2.txt', 'r') as other_file:              # 第二個上下文管理器                  for line in other_file:              print(line.strip())           

但我們可以輕易地在一個語句中打開多個檔案。如果你想将一行寫入另一個檔案,這非常簡便:

with open('file1.txt') as file1, open('file2.txt') as file2:              # 同時使用 file1 和 file2 的代碼              # 檔案将在塊結束時自動關閉              # 即使發生異常                  # 示例:從檔案 1 讀取行并将其寫入檔案 2              for line in file1:              file2.write(line)           
Python:被忽視的核心功能

Python 調試器

我們可以在我們的檔案中列印大量的變量進行調試,或者我們可以簡單地使用 Python 調試器 (pdb),它幫助我們設定斷點,使得操作更加簡單:

import pdb                  # 在你的代碼中設定這個斷點              pdb.set_trace()           

使這個功能更有價值的是,程式會在你設定的斷點處停止,你可以列印任何變量來檢查其在特定斷點處的值或存在情況。試試看!當程式觸發一個斷點時,你可以使用以下幾個指令:

  • n 或 next:執行下一行。
  • s 或 step:步入函數調用。
  • c 或 continue:繼續執行直到下一個斷點。
  • l 或 list:顯示目前的代碼上下文。
  • p <expression> 或 pp <expression>:列印表達式的值。
  • b <line> 或 break <line>:在指定的行設定一個新的斷點。
  • h 或 help:擷取關于 pdb 的使用幫助。
  • q 或 quit:退出調試器并終止程式。
Python:被忽視的核心功能

collections.Counter

collections 子產品中的 Counter 類提供了一種便捷的方式來計算可疊代對象中的元素個數:

Counter``collections           
from collections import Counter                  my_list = [1, 2, 3, 1, 2, 1, 3, 4, 5]              counts = Counter(my_list)              print(counts) # 輸出: 計數器({1: 3, 2: 2, 3: 2, 4: 1, 5: 1})           
Python:被忽視的核心功能

使用 Itertools 實作組合

我們可以組合不同的 for 循環來建立排列、組合或笛卡爾積,或者我們可以簡單地使用内建的 itertools。

Python:被忽視的核心功能

Permutations(排列)

import itertools                  # 生成排列              perms = itertools.permutations([1, 2, 3], 2)              print(list(perms)) # 輸出: [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]           
Python:被忽視的核心功能

Combinations(組合)

import itertools                  # 生成組合              combs = itertools.combinations('ABC', 2)              print(list(combs)) # 輸出: [('A', 'B'), ('A', 'C'), ('B', 'C')]           
Python:被忽視的核心功能

Cartesian product(笛卡爾積)

import itertools                  # 生成笛卡爾積              cartesian = itertools.product('AB', [1, 2])              print(list(cartesian)) # 輸出: [('A', 1), ('A', 2), ('B', 1), ('B', 2)]           
Python:被忽視的核心功能

下劃線的兩種用法

下面是在 Python 中使用下劃線的兩種方式:作為大數字的分隔符或作為丢棄變量。

Python:被忽視的核心功能

丢棄變量

下劃線 _ 可以用作丢棄變量,用來丢棄不想要的值:

# 忽略函數的第一個傳回值              _, result = some_function()                  # 不使用循環變量進行循環              for _ in range(5):              do_something()                  # 你隻需要第一個和最後一個              first, *_, last = [1, 2, 3, 4, 5]           
Python:被忽視的核心功能

大數字的分隔符

在處理大數字值時,你可以使用下劃線 (_) 作為視覺分隔符以提高可讀性。這個特性在 Python 3.6 中被引入,被稱為 "下劃線字面量"。

population = 7_900_000_000              revenue = 3_249_576_382.50                  print(population) # 輸出: 7900000000              print(revenue) # 輸出: 3249576382.5           

你知道 Python 中還有哪些容易被忽略的好用功能或技巧?歡迎在評論區留言分享。

粉絲福利: