摘要:本文為你帶來如何找到長度內建資料型別的使用len() 使用len()與第三方資料型別 提供用於支援len()與使用者定義的類。
本文分享自華為雲社群《在 Python 中使用 len() 函式》,作者:Yuchuan 。
在許多情況下,您需要找到儲存在資料結構中的專案數。Python 的內建函式len()是幫助您完成此任務的工具。
在某些情況下, 的使用len()很簡單。但是,有時您需要更詳細地瞭解此函式的工作原理以及如何將其應用於不同的資料型別。
在本教程中,您將學習如何:
- 找到的長度內建資料型別的使用len()
- 使用len()與第三方資料型別
- 提供用於支援len()與使用者定義的類
在本文結束時,您將知道何時使用len()Python 函式以及如何有效地使用它。您將知道哪些內建資料型別是有效引數len(),哪些不能使用。您還可以瞭解如何使用len()第三方型別,如ndarray在與NumPy和DataFrame在大熊貓,並用自己的類。
Python 入門 len()
該函式len()是 Python 的內建函式之一。它返回物件的長度。例如,它可以返回列表中的專案數。您可以將該函式用於許多不同的資料型別。但是,並非所有資料型別都是 的有效引數len()。
您可以從檢視此功能的幫助開始:
>>> >>> help(len) Help on built-in function len in module builtins: len(obj, /) Return the number of items in a container.
該函式將一個物件作為引數並返回該物件的長度。該檔案對len()去遠一點:
返回物件的長度(專案數)。引數可以是序列(例如字串、位元組、元組、列表或範圍)或集合(例如字典、集合或凍結集合)。(來源)
當您使用內建資料型別和許多帶有 的第三方型別時len(),該函式不需要遍歷資料結構。容器物件的長度儲存為物件的屬性。每次在資料結構中新增或刪除專案時,都會修改此屬性len()的值,並返回長度屬性的值。這確保了len()有效地工作。
在以下部分中,您將瞭解如何使用len()序列和集合。您還將瞭解一些不能用作len()Python 函式引數的資料型別。
使用len()內建序列
一個序列是訂購物品的容器。列表、元組和字串是 Python 中的三個基本內建序列。您可以通過呼叫找到序列的長度len():
>>> >>> greeting = "Good Day!" >>> len(greeting) 9 >>> office_days = ["Tuesday", "Thursday", "Friday"] >>> len(office_days) 3 >>> london_coordinates = (51.50722, -0.1275) >>> len(london_coordinates) 2
在查詢 string greeting、 listoffice_days和 tuple的長度時london_coordinates,您len()以相同的方式使用。所有三種資料型別都是 的有效引數len()。
該函式len()始終返回一個整數,因為它正在計算您傳遞給它的物件中的專案數。0如果引數是空序列,則函式返回:
>>> >>> len("") 0 >>> len([]) 0 >>> len(()) 0
在上面的例子中,你找到了一個空字串、一個空列表和一個空元組的長度。該函式0在每種情況下都返回。
一個range物件也可以建立使用序列range()。一個range物件不儲存所有的值,但它們產生在需要時他們。但是,您仍然可以range使用len()以下方法找到物件的長度:
>>> >>> len("") 0 >>> len([]) 0 >>> len(()) 0
此數字範圍包括從1到19增量為的整數2。range物件的長度可以通過開始、停止和步長值來確定。
在本節中,您已將len()Python 函式用於字串、列表、元組和range物件。但是,您也可以將該函式與任何其他內建序列一起使用。
使用len()帶內建集合
在某些時候,您可能需要在列表或其他序列中查詢唯一項的數量。您可以使用集和len()來實現這一點:
>>> >>> import random >>> numbers = [random.randint(1, 20) for _ in range(20)] >>> numbers [3, 8, 19, 1, 17, 14, 6, 19, 14, 7, 6, 1, 17, 10, 8, 14, 17, 10, 2, 5] >>> unique_numbers = set(numbers) {1, 2, 3, 5, 6, 7, 8, 10, 14, 17, 19} >>> len(unique_numbers) 11
您numbers使用列表推導式生成列表,它包含 20 個介於1和之間的隨機數20。由於您生成的是隨機數,因此每次執行程式碼時輸出都會不同。在這個特定的執行中,有 20 個隨機生成的數字列表中有 11 個唯一數字。
您將經常使用的另一種內建資料型別是dictionary。在字典中,每一項都由一個鍵值對組成。當您使用字典作為 的引數時len(),該函式返回字典中的專案數:
>>> >>> len({"James": 10, "Mary": 12, "Robert": 11}) 3 >>> len({}) 0
第一個示例的輸出顯示此字典中有三個鍵值對。與序列的情況一樣,當引數是空字典或空集時len()將返回0。這導致空字典和空集為假。
探索len()其他內建資料型別
您不能使用所有內建資料型別作為len(). 對於其中不儲存多個專案的資料型別,長度的概念不相關。這是數字和布林型別的情況:
>>> >>> len(5) Traceback (most recent call last): ... TypeError: object of type 'int' has no len() >>> len(5.5) Traceback (most recent call last): ... TypeError: object of type 'float' has no len() >>> len(True) Traceback (most recent call last): ... TypeError: object of type 'bool' has no len() >>> len(5 + 2j) Traceback (most recent call last): ... TypeError: object of type 'complex' has no len()
該整數,浮點數,布林,以及複雜型別的內建資料型別,你不能使用示例len()。TypeError當引數是沒有長度的資料型別的物件時,該函式會引發 a 。
您還可以探索是否可以使用迭代器和生成器作為引數len():
>>> >>> import random >>> numbers = [random.randint(1, 20) for _ in range(20)] >>> len(numbers) 20 >>> numbers_iterator = iter(numbers) >>> len(numbers_iterator) Traceback (most recent call last): ... TypeError: object of type 'list_iterator' has no len() >>> numbers_generator = (random.randint(1, 20) for _ in range(20)) >>> len(numbers_generator) Traceback (most recent call last): ... TypeError: object of type 'generator' has no len()
您已經看到列表具有長度,這意味著您可以將其用作len(). 您可以使用內建函式從列表中建立一個迭代器iter()。在迭代器中,只要需要,就會獲取每個專案,例如在使用函式next()或在迴圈中時。但是,您不能在len().
你得到了TypeError,當您嘗試使用一個迭代器作為一個引數len()。由於迭代器在需要時獲取每個專案,因此測量其長度的唯一方法是耗盡迭代器。迭代器也可以是無限的,例如由 返回的迭代器itertools.cycle(),因此它的長度無法定義。
不能使用發電機與len()出於同樣的原因。如果不使用它們,就無法測量這些物體的長度。
len()用一些例子進一步探索
在本節中,您將瞭解len(). 這些示例將幫助您更好地瞭解何時使用此功能以及如何有效地使用它。在某些示例中,您還將看到len()可能的解決方案但可能有更多 Pythonic 方法來實現相同輸出的情況。
驗證使用者輸入的長度
的一個常見用例len()是驗證使用者輸入的序列的長度:
# username.py username = input("Choose a username: [4-10 characters] ") if 4 <= len(username) <= 10: print(f"Thank you. The username {username} is valid") else: print("The username must be between 4 and 10 characters long")
在此示例中,您使用if語句來檢查 返回的整數len()是否大於或等於4且小於或等於10。你可以執行這個指令碼,你會得到一個類似於下面的輸出:
$ python username.py Choose a username: [4-10 characters] stephen_g Thank you. The username stephen_g is valid
在這種情況下,使用者名稱的長度為 9 個字元,因此if語句中的條件計算結果為True。您可以再次執行指令碼並輸入無效的使用者名稱:
$ python username.py Choose a username: [4-10 characters] sg The username must be between 4 and 10 characters long
在這種情況下,len(username)返回2,並且if語句中的條件計算結果為False。
根據物件的長度結束迴圈
len()如果您需要檢查可變序列(例如列表)的長度何時達到特定數字,您將使用。在以下示例中,您要求使用者輸入三個使用者名稱選項,並將它們儲存在列表中:
# username.py usernames = [] print("Enter three options for your username") while len(usernames) < 3: username = input("Choose a username: [4-10 characters] ") if 4 <= len(username) <= 10: print(f"Thank you. The username {username} is valid") usernames.append(username) else: print("The username must be between 4 and 10 characters long") print(usernames)
您現在使用的從結果len()的while宣告。如果使用者輸入了無效的使用者名稱,您不會保留輸入。當使用者輸入有效字串時,您將其附加到列表中usernames。迴圈重複,直到列表中有三個專案。
您甚至可以len()用來檢查序列何時為空:
>>> >>> colors = ["red", "green", "blue", "yellow", "pink"] >>> while len(colors) > 0: ... print(f"The next color is {colors.pop(0)}") ... The next color is red The next color is green The next color is blue The next color is yellow The next color is pink
您使用 list 方法.pop()在每次迭代中從列表中刪除第一項,直到列表為空。如果您在大型列表上使用此方法,則應從列表末尾刪除專案,因為這樣效率更高。您還可以使用內建模組中的deque資料型別collections,它允許您有效地從左側彈出。
通過使用序列的真實性,有一種更 Pythonic 的方式來實現相同的輸出:
>>> >>> colors = ["red", "green", "blue", "yellow", "pink"] >>> while colors: ... print(f"The next color is {colors.pop(0)}") ... The next color is red The next color is green The next color is blue The next color is yellow The next color is pink
空列表是假的。這意味著該while語句將空列表解釋為False。非空列表是真實的,while語句將其視為True. 返回的值len()決定了序列的真實性。一個序列是truthy當len()返回任何非零整數,並且當falsylen()返回0。
查詢序列最後一項的索引
想象一下,您想要生成一個範圍1為的隨機數序列,10並且您希望不斷向該序列新增數字,直到所有數字的總和超過21。以下程式碼建立一個空列表並使用while迴圈填充列表:
>>> >>> import random >>> numbers = [] >>> while sum(numbers) <= 21: ... numbers.append(random.randint(1, 10)) >>> numbers [3, 10, 4, 7] >>> numbers[len(numbers) - 1] 7 >>> numbers[-1] # A more Pythonic way to retrieve the last item 7 >>> numbers.pop(len(numbers) - 1) # You can use numbers.pop(-1) 7 >>> numbers [3, 10, 4]
您將隨機數附加到列表中,直到總和超過21。當您生成隨機數時,您將獲得的輸出會有所不同。要顯示列表中的最後一個數字,請使用它len(numbers)並1從中減去,因為列表的第一個索引是0。Python 中的索引允許您使用索引-1來獲取列表中的最後一項。因此,雖然您可以len()在這種情況下使用,但您不需要。
您想刪除列表中的最後一個數字,以便列表中所有數字的總和不超過21。您len()再次使用來計算列表中最後一項的索引,您將其用作列表方法的引數.pop()。即使在這種情況下,您也可以將其-1用作.pop()從列表中刪除最後一項並返回它的引數。
將列表分成兩半
如果需要將序列分成兩半,則需要使用表示序列中點的索引。您可以使用len()來查詢此值。在以下示例中,您將建立一個隨機數列表,然後將其拆分為兩個較小的列表:
>>> >>> import random >>> numbers = [random.randint(1, 10) for _ in range(10)] >>> numbers [9, 1, 1, 2, 8, 10, 8, 6, 8, 5] >>> first_half = numbers[: len(numbers) // 2] >>> second_half = numbers[len(numbers) // 2 :] >>> first_half [9, 1, 1, 2, 8] >>> second_half [10, 8, 6, 8, 5]
在定義 的賦值語句中first_half,使用表示從開頭numbers到中點的專案的切片。您可以通過分解切片表示式中使用的步驟來計算切片表示的內容:
- 首先,len(numbers)返回整數10。
- 接下來,10 // 2在5使用整數除法運算子時返回整數。
- 最後,0:5是一個切片,表示前五個專案,其索引0為4。請注意,端點被排除在外。
在下一個定義中second_half,在切片中使用相同的表示式。但是,在這種情況下,整數5表示範圍的開始。切片現在5:代表從索引5到列表末尾的專案。
如果您的原始列表包含奇數個專案,則其長度的一半將不再是整數。當您使用整數除法時,您將獲得數字的下限。該列表first_half現在將比 少一項second_half。
您可以通過建立一個包含 11 個數字而不是 10 個數字的初始列表來嘗試這一點。結果列表將不再是一半,但它們將代表最接近拆分奇數序列的替代方法。
將len()函式與第三方庫一起使用
您還可以將 Pythonlen()與來自第三方庫的多種自定義資料型別結合使用。在本教程的最後一節中,您將瞭解 的行為如何len()取決於類定義。在本節中,您將檢視使用len()來自兩個流行的第三方庫的資料型別的示例。
NumPy 的 ndarray
該NumPy的模組是在Python程式設計的所有定量應用的基石。該模組介紹了numpy.ndarray資料型別。這種資料型別以及 NumPy 中的函式非常適合數值計算,並且是其他模組中資料型別的構建塊。
在開始使用 NumPy 之前,您需要安裝該庫。您可以使用 Python 的標準包管理器pip,並在控制檯中執行以下命令:
$ python -m pip install numpy
您已經安裝了 NumPy,現在您可以從列表中建立一個 NumPy 陣列並len()在該陣列上使用:
>>> >>> import numpy as np >>> numbers = np.array([4, 7, 9, 23, 10, 6]) >>> type(numbers) <class 'numpy.ndarray'> >>> len(numbers) 6
NumPy 函式從您作為引數傳遞的列表中np.array()建立一個型別的物件numpy.ndarray。
但是,NumPy 陣列可以有多個維度。您可以通過將列表列表轉換為陣列來建立二維陣列:
>>> >>> import numpy as np >>> numbers = [ [11, 1, 10, 10, 15], [14, 9, 16, 4, 4], ] >>> numbers_array = np.array(numbers) >>> numbers_array array([[11, 1, 10, 10, 15], [14, 9, 16, 4, 4]]) >>> len(numbers_array) 2 >>> numbers_array.shape (2, 5) >>> len(numbers_array.shape) 2 >>> numbers_array.ndim 2
該列表numbers由兩個列表組成,每個列表包含五個整數。當您使用此列表列表建立 NumPy 陣列時,結果是一個包含兩行五列的陣列。當您將此二維陣列作為引數傳遞給 中時,該函式返回陣列中的行數len()。
要獲得兩個維度的大小,您可以使用屬性.shape,它是一個顯示行數和列數的元組。您可以通過使用.shape和len()或通過使用 屬性來獲取 NumPy 陣列的維數.ndim。
一般來說,當你有一個任意維數的陣列時,len()返回第一維的大小:
>>> >>> import numpy as np >>> array_3d = np.random.randint(1, 20, [2, 3, 4]) >>> array_3d array([[[14, 9, 15, 14], [17, 11, 10, 5], [18, 1, 3, 12]], [[ 1, 5, 6, 10], [ 6, 3, 1, 12], [ 1, 4, 4, 17]]]) >>> array_3d.shape (2, 3, 4) >>> len(array_3d) 2
在本例中,您將建立一個三維陣列,其形狀為(2, 3, 4)其中每個元素都是1和之間的隨機整數20。這次您使用該函式np.random.randint()建立了一個陣列。函式len()返回2,這是第一個維度的大小。
檢視NumPy 教程:您在 Python 中進入資料科學的第一步,瞭解有關使用 NumPy 陣列的更多資訊。
Pandas’ DataFrame
pandas庫中的DataFrame型別是另一種在許多應用程式中廣泛使用的資料型別。
在使用 pandas 之前,您需要在控制檯中使用以下命令進行安裝:
$ python -m pip install pandas
您已經安裝了 pandas 包,現在您可以從字典建立一個 DataFrame:
>>> >>> import pandas as pd >>> marks = { "Robert": [60, 75, 90], "Mary": [78, 55, 87], "Kate": [47, 96, 85], "John": [68, 88, 69], } >>> marks_df = pd.DataFrame(marks, index=["Physics", "Math", "English"]) >>> marks_df Robert Mary Kate John Physics 60 78 47 68 Math 75 55 96 88 English 90 87 85 69 >>> len(marks_df) 3 >>> marks_df.shape (3, 4)
字典的鍵是代表班級學生姓名的字串。每個鍵的值是一個列表,其中包含三個主題的標記。當您從此字典建立 DataFrame 時,您可以使用包含主題名稱的列表來定義索引。
DataFrame 有三行四列。該函式len()返回 DataFrame 中的行數。該DataFrame型別還有一個.shape屬性,您可以使用它來顯示 DataFrame 的第一個維度表示行數。
您已經瞭解瞭如何len()使用許多內建資料型別以及來自第三方模組的一些資料型別。在下一節中,您將學習如何定義任何類,以便將其用作len()Python 函式的引數。
您可以在The Pandas DataFrame: Make Working With Data Delightful 中進一步探索 pandas 模組。
使用len()使用者定義的類
當您定義一個類時,您可以定義的特殊方法之一是.__len__(). 這些特殊方法被稱為 dunder 方法,因為它們在方法名稱的開頭和結尾都有雙下劃線。Python 的內建len()函式呼叫其引數的.__len__()方法。
在上一節中,您已經看到了len()當引數是一個 pandasDataFrame物件時的行為。此行為由類的.__len__()方法決定DataFrame,您可以在以下模組的原始碼中看到pandas.core.frame:
class DataFrame(NDFrame, OpsMixin): # ... def __len__(self) -> int: """ Returns length of info axis, but here we use the index. """ return len(self.index)
此方法使用 返回 DataFrame.index屬性的長度len()。此 dunder 方法將 DataFrame 的長度定義為等於 DataFrame 中的行數,如 所示.index。
您可以.__len__()通過以下玩具示例進一步探索dunder 方法。您將定義一個名為YString. 此資料型別基於內建字串類,但型別物件YString賦予字母 Y 比所有其他字母更重要:
# ystring.py class YString(str): def __init__(self, text): super().__init__() def __str__(self): """Display string as lowercase except for Ys that are uppercase""" return self.lower().replace("y", "Y") def __len__(self): """Returns the number of Ys in the string""" return self.lower().count("y")
.__init__()方法YString使用.__init__()父str類的方法初始化物件。您可以使用函式來實現這一點super()。該.__str__()方法定義了物件的顯示方式。函式str()、print()和format()都呼叫此方法。對於此類,您將物件表示為全小寫字串,但字母 Y 除外,它顯示為大寫。
對於這個玩具類,您將物件的長度定義為字串中字母 Y 的出現次數。因此,該.__len__()方法返回字母 Y 的計數。
您可以建立一個類的物件YString並找到它的長度。用於上述示例的模組名稱是ystring.py:
>>> >>> from ystring import YString >>> message = YString("Real Python? Yes! Start reading today to learn Python") >>> print(message) real pYthon? Yes! start reading todaY to learn pYthon >>> len(message) # Returns number of Ys in message 4
您YString從型別物件建立型別物件str並使用 顯示物件的表示print()。然後將該物件message用作 的引數len()。這將呼叫類的.__len__()方法,結果是字母 Y 在 中的出現次數message。在這種情況下,字母 Y 出現了四次。
YString該類不是一個非常有用的類,但它有助於說明如何自定義 的行為len()以滿足您的需要。該.__len__()方法必須返回一個非負整數。否則,它會引發錯誤。
另一個特殊的方法是.__bool__()方法,它決定了如何將物件轉換為布林值。該.__bool__()dunder方法通常不用於序列和集合定義。在這些情況下,該.__len__()方法確定物件的真實性:
>>> >>> from ystring import YString >>> first_test = "tomorrow" >>> second_test = "today" >>> bool(first_test) True >>> bool(YString(first_test)) False >>> bool(second_test) True >>> bool(YString(second_test)) True
變數first_string中沒有 Y。如 的輸出所示bool(),該字串為真,因為它非空。但是,當您YString從此字串建立型別的物件時,新物件是假的,因為字串中沒有 Y 字母。因此,len()返回0。相反,變數second_string確實包含字母 Y,因此字串和型別的物件YString都是真值。
您可以在 Python 3 中的物件導向程式設計 (OOP) 中閱讀有關使用物件導向程式設計和定義類的更多資訊。
結論
您已經探索瞭如何使用len()來確定序列、集合和其他同時包含多個專案的資料型別(例如 NumPy 陣列和 Pandas DataFrames)中的專案數量。
該len()Python函式是在許多程式中的關鍵工具。它的一些用途很簡單,但正如您在本教程中看到的那樣,此功能比最基本的用例要多得多。瞭解何時可以使用此功能以及如何有效地使用它將有助於您編寫更整潔的程式碼。
在本教程中,您學習瞭如何:
- 找到的長度內建資料型別的使用len()
- 使用len()與第三方資料型別
- 提供用於支援len()與使用者定義的類
您現在已為理解該len()函式奠定了良好的基礎。len()瞭解更多 about可以幫助您更好地理解資料型別之間的差異。您已準備好在len()您的演算法中使用,並通過使用.__len__()方法增強某些類定義來改進它們的功能。