Python編程中被忽視的核心技巧總結(jié)
這篇文章主要介紹了一些在 Python 編程中可能被忽視的核心功能,包括默認參數(shù)、海象運算符、*args 和 **kwargs 的使用、變量交換、str 與 repr 的區(qū)別、可迭代對象的擴展解包、多個上下文管理器的使用、Python 調(diào)試器、collections.Counter 的使用、itertools 的使用以及下劃線的兩種用法等。
因為這門語言非常容易學,許多實踐者只是了解了它的基礎(chǔ)知識,而忽略了深入探討這門語言更高級和強大的方面,這也是它真正獨特和強大的地方。
所以,讓我們簡要討論一下所有你可能還沒有聽說過的功能,但如果你想成為一名真正經(jīng)驗豐富的 Pythonista,你肯定想了解。
參數(shù)默認值
需要重點注意的是,Python 的參數(shù)在遇到函數(shù)定義時就進行評估。這意味著每次調(diào)用 fib_memo 函數(shù)(下文會提到)而沒有明確提供 memo 參數(shù)的值時,它將使用函數(shù)定義時創(chuàng)建的相同字典對象。
def fib_memo(n, memo={0:0, 1:1}): """ n 是你想要返回的序列中的第 n 個數(shù)字 """ if not n in memo: memo[n] = fib_memo(n-1) + fib_memo(n-2) return memo[n] # 返回一個介于0和100之間(包括0和100)的數(shù)字。 fib_memo(6) # 應(yīng)該返回8
這段代碼在 Python 中可以正常運行。這也意味著你可以在一個腳本中多次執(zhí)行 fib_memo 函數(shù),比如在一個 for 循環(huán)中,每次執(zhí)行都會增加要計算的 fibonacci 數(shù)字,而不會達到“超過最大遞歸深度”的限制,因為 memo 會不斷擴展。關(guān)于這方面的更多信息可以在我的另一篇文章中找到。
海象操作符
海象操作符 (:= ) 是在 Python 3.8 中引入的,它允許你在表達式中為變量賦值。這樣,你可以在一個表達式中為變量賦值并檢查其值:
import random some_value = random.randint(0,100) # 返回一個介于0和100之間(包括0和100)的數(shù)字。 if((below_ten := some_value) < 10): print(f"{below_ten} 小于 10")
顯然,它也可以方便地賦值并檢查返回的值是否包含真值:
if(result := some_method()): # 如果結(jié)果不為假值(Falsy) print(result)
*args 和 **kwargs
通過星號 (* ),你可以在傳遞給函數(shù)之前解包參數(shù)或關(guān)鍵字參數(shù)(使用 ** )。
例如,考慮以下代碼:
my_numbers = [1,2] def sum_numbers(first_number, second_number): return first_number + second_number # 這將返回一個類型錯誤。 # 類型錯誤:sum() 缺少 1 個必需的位置參數(shù):“second_number” sum_numbers(my_numbers) #這將返回預(yù)期的結(jié)果,3。 sum_numbers(*my_numbers)
當我們調(diào)用 sum_numbers 函數(shù)時,如果不解包 my_numbers,它會引發(fā)一個 TypeError ,因為函數(shù)期望兩個獨立的參數(shù)。然而,通過使用星號 (*),我們可以從 my_numbers 中解包值并將它們作為獨立的參數(shù)傳遞,從而得到正確的輸出。
這種解包技術(shù)不僅適用于元組和列表,還適用于字典(盡管它會將鍵作為參數(shù)傳遞)。那么關(guān)鍵字參數(shù)呢?對此,我們可以利用雙星號 (**)。以下代碼作為例子:
def greet_person(last_name, first_name): print(f"Hello {first_name} {last_name}") data = {"first_name": "John", "last_name": "Doe"} greet_person(**data)
除了解包一個序列來將它們作為函數(shù)的參數(shù),你也可以用它來創(chuàng)建一個新的序列,例如:
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]]
any 和 all
any 和 all 是兩個內(nèi)建函數(shù),它們對可迭代對象(如列表、元組或集合)進行操作,并基于可迭代對象中的元素返回一個布爾值。
例如:
some_booleans = [True, False, False, False] any(some_booleans) # 返回 True all(some_booleans) # 返回 False
你可以將 all 和 any 函數(shù)與列表推導(dǎo)式結(jié)合使用,它返回一個可迭代的結(jié)果并將其作為參數(shù)傳遞給 all 函數(shù):
numbers = [5, 10, 3, 8, -2] all_positive = all(num > 0 for num in numbers)
… 或 any 函數(shù):
fruits = ['apple', 'banana', 'cherry', 'durian'] # 檢查是否所有水果都以“a”開頭 result = all(fruit.startswith('a') for fruit in fruits) print(result)
下面的表格顯示了根據(jù)可迭代對象中的值返回的輸出的不同。
變量交換
你可以組合元組打包(在等號 (=) 右邊發(fā)生)和解包(在等號 (=) 左邊發(fā)生),并利用這個功能進行變量交換:
a = 10 b = 5 # 通過打包和解包交換 b 和 a 的值 a, b = b, a print(a) #5 print(b) #10
str vs repr
我們習慣于使用 str(some_value) 將某個變量或值轉(zhuǎn)換為字符串,以便于進行調(diào)試打印。我想讓你了解 repr(some_value)。主要的區(qū)別是 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() 提供了有關(guān)變量所持有的實際對象的信息。在調(diào)試過程中,這個信息會更有價值。
擴展的可迭代對象解包
這個可以簡單理解:如果你想通過一個命令獲取序列的第一個和最后一個值:
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
或者其他組合。
多個上下文管理器
我們習慣于一次使用一個上下文管理器,比如打開一個文件:
with open('file.txt', 'r') as file: # 使用該文件的代碼 # 該文件將在塊結(jié)束時自動關(guān)閉 # 即使發(fā)生異常 # 示例:從文件中讀取行 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 的代碼 # 文件將在塊結(jié)束時自動關(guān)閉 # 即使發(fā)生異常 # 示例:從文件 1 讀取行并將其寫入文件 2 for line in file1: file2.write(line)
Python 調(diào)試器
我們可以在我們的文件中打印大量的變量進行調(diào)試,或者我們可以簡單地使用 Python 調(diào)試器 (pdb),它幫助我們設(shè)置斷點,使得操作更加簡單:
import pdb # 在你的代碼中設(shè)置這個斷點 pdb.set_trace()
使這個功能更有價值的是,程序會在你設(shè)置的斷點處停止,你可以打印任何變量來檢查其在特定斷點處的值或存在情況。試試看!當程序觸發(fā)一個斷點時,你可以使用以下幾個命令:
- n 或 next:執(zhí)行下一行。
- s 或 step:步入函數(shù)調(diào)用。
- c 或 continue:繼續(xù)執(zhí)行直到下一個斷點。
- l 或 list:顯示當前的代碼上下文。
- p 或 pp :打印表達式的值。
- b 或 break :在指定的行設(shè)置一個新的斷點。
- h 或 help:獲取關(guān)于 pdb 的使用幫助。
- q 或 quit:退出調(diào)試器并終止程序。
collections.Counter
collections 模塊中的 Counter 類提供了一種便捷的方式來計算可迭代對象中的元素個數(shù):
Counter``collections
from collections import Counter my_list = [1, 2, 3, 1, 2, 1, 3, 4, 5] counts = Counter(my_list) print(counts) # 輸出: 計數(shù)器({1: 3, 2: 2, 3: 2, 4: 1, 5: 1})
使用 Itertools 實現(xiàn)組合
我們可以組合不同的 for 循環(huán)來創(chuàng)建排列、組合或笛卡爾積,或者我們可以簡單地使用內(nèi)建的 itertools。
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)]
Combinations(組合)
import itertools # 生成組合 combs = itertools.combinations('ABC', 2) print(list(combs)) # 輸出: [('A', 'B'), ('A', 'C'), ('B', 'C')]
Cartesian product(笛卡爾積)
import itertools # 生成笛卡爾積 cartesian = itertools.product('AB', [1, 2]) print(list(cartesian)) # 輸出: [('A', 1), ('A', 2), ('B', 1), ('B', 2)]
下劃線的兩種用法
下面是在 Python 中使用下劃線的兩種方式:作為大數(shù)字的分隔符或作為丟棄變量。
丟棄變量
下劃線 _ 可以用作丟棄變量,用來丟棄不想要的值:
# 忽略函數(shù)的第一個返回值 _, result = some_function() # 不使用循環(huán)變量進行循環(huán) for _ in range(5): do_something() # 你只需要第一個和最后一個 first, *_, last = [1, 2, 3, 4, 5]
大數(shù)字的分隔符
在處理大數(shù)字值時,你可以使用下劃線 (_) 作為視覺分隔符以提高可讀性。這個特性在 Python 3.6 中被引入,被稱為 “下劃線字面量”。
population = 7_900_000_000 revenue = 3_249_576_382.50 print(population) # 輸出: 7900000000 print(revenue) # 輸出: 3249576382.5
到此這篇關(guān)于Python編程中被忽視的核心技巧總結(jié)的文章就介紹到這了,更多相關(guān)Python技巧內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PyCharm創(chuàng)建Django項目的簡單步驟記錄
PyCharm是一種Python?IDE,帶有一整套可以幫助用戶在使用Python語言開發(fā)時提高其效率的工具,下面這篇文章主要給大家介紹了關(guān)于利用PyCharm創(chuàng)建Django項目的簡單步驟,需要的朋友可以參考下2022-07-07matplotlib 曲線圖 和 折線圖 plt.plot()實例
這篇文章主要介紹了matplotlib 曲線圖 和 折線圖 plt.plot()實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04Python中函數(shù)eval和ast.literal_eval的區(qū)別詳解
eval函數(shù)在Python中做數(shù)據(jù)類型的轉(zhuǎn)換還是很有用的。它的作用就是把數(shù)據(jù)還原成它本身或者是能夠轉(zhuǎn)化成的數(shù)據(jù)類型。那么eval和ast.literal_val()的區(qū)別是什么呢?本文將大家介紹關(guān)于Python中函數(shù)eval和ast.literal_eval區(qū)別的相關(guān)資料,需要的朋友可以參考下。2017-08-08Python使用tarfile模塊實現(xiàn)免費壓縮解壓
Python自帶的tarfile模塊可以方便讀取tar歸檔文件,厲害的是可以處理使用gzip和bz2壓縮歸檔文件tar.gz和tar.bz2,這篇文章主要介紹了Python使用tarfile模塊實現(xiàn)免費壓縮解壓,需要的朋友可以參考下2024-03-03