Python的函式(內建函式和我們自己編寫的自定義函式)是處理資料的關鍵工具。但是他們對資料的處理可能會有些混亂,如果我們不知道發生了什麼,可能會導致分析中的嚴重錯誤。
在python函式控制列表和詞典中,我們將仔細研究Python在函式內部進行操作時如何對待不同的資料型別,並學習如何確保僅在需要更改資料時才更改資料。
功能中的記憶體隔離
要了解Python如何處理函式內部的全域性變數,讓我們做一些實驗。我們將建立兩個全域性變數number_1和number_2,並將它們分配給整數5and 10。然後,我們將這些全域性變數用作執行一些簡單數學運算的函式中的引數。我們還將變數名用作函式的引數名。然後,我們將檢視函式內部的所有變數用法是否已影響這些變數的全域性值。
正如我們可以看到上面的功能工作正常,以及全球變數的值number_1,並number_2沒有不改變,即使我們用它們作為引數,並在我們的函式的引數名稱。這是因為Python將函式的變數儲存在與全域性變數不同的記憶體位置中。它們是孤立的。因此,變數number_1在全域性範圍內可以具有一個值(5),而在函式內部則可以具有不同的值(50),在此將其隔離。
列表和詞典呢?
清單
我們已經看到,對number_1函式內部的上述變數執行的操作不會影響其全域性值。但是number_1是一個整數,這是一個非常基本的資料型別。如果我們嘗試使用不同的資料型別(例如列表)進行相同的實驗,會發生什麼?在下面,我們將建立一個名為的函式duplicate_last(),該函式將在我們將其作為引數傳遞的任何列表中複製最終條目。
如我們所見,即使僅在函式中更改了全域性值,此處的全域性值也initial_list 已更新!
辭典
現在,讓我們編寫一個將字典作為引數的函式,以檢視在函式內部對全域性字典變數進行修改時是否也會對其進行修改。
為了使這一點更加現實,我們將使用Python基礎知識課程中AppleStore.csv使用的資料集中的資料(可在此處下載資料)。
在下面的程式碼段中,我們從一個字典開始,該字典包含資料集中每個年齡等級的應用程式數量的計數(因此,有4,433個應用程式的等級為“ 4 +”,987個應用程式的等級為“ 9+”,等等。) 。假設我們要為每個年齡等級計算一個百分比,這樣我們就可以瞭解到哪個年齡等級在App Store中最常見。
為此,我們將編寫一個名為的函式make_percentages(),該函式將字典作為引數並將計數轉換為百分比。我們需要從零開始計數,然後對字典中的每個值進行迭代,然後將它們新增到計數中,以便獲得評分的總數。然後,我們將再次遍歷字典,並對每個值進行一些數學運算以計算百分比。
在檢視輸出之前,讓我們快速回顧一下上面發生的事情。在將應用程式年齡分級的字典分配給變數後content_ratings,我們建立了一個名為的新函式make_percentages(),該函式帶有一個引數:a_dictionary。
為了圖什麼應用程式的比例下降到每一個年齡分級,我們需要知道應用程式的總數,所以我們先設定一個所謂的新的變數total,以0透過在每個鍵,然後迴圈a_dictionary,將它新增到total。
一旦完成,我們要做的就是a_dictionary再次迴圈遍歷,將每個條目除以總數,然後將結果乘以100。這將為我們提供帶有百分比的字典。
但是,當我們使用global content_ratings作為該新函式的引數時會發生什麼呢?
就像我們在列表中看到的一樣content_ratings,即使僅在make_percentages()我們建立的函式內部對其進行了修改,我們的全域性變數也已更改。
那麼,這裡到底發生了什麼?我們碰到了可變和不可變資料型別之間的差異。
可變和不可變資料型別
在Python中,資料型別可以是可變的(可變的)或不可變的(不變的)。儘管我們在Python入門中使用的大多數資料型別都是不可變的(包括整數,浮點數,字串,布林值和元組),但列表和字典卻是可變的。這意味著全域性列表或字典即使在函式內部使用時也可以更改,就像我們在上面的示例中看到的那樣。
要了解可變(可變)和不可變(不變)之間的區別,研究一下Python如何實際處理這些變數是有幫助的。
讓我們開始考慮一個簡單的變數賦值:
變數名的a作用類似於指向的指標5,它可以幫助我們5在需要時進行檢索。
5是整數,整數是不可變的資料型別。如果資料型別是不可變的,則意味著它一旦建立便無法更新。如果這樣做a += 1,我們實際上5並沒有更新到6。在下面的動畫中,我們可以看到:
1)a最初指向5。
2)a += 1執行,並將指標從5移到6,實際上並沒有改變number 5。
列表和字典等可變資料型別的行為有所不同。它們可以被更新。因此,例如,讓我們列出一個非常簡單的列表:
如果將a附加3到此列表的末尾,我們不僅會指向list_1其他列表,還會直接更新現有列表:
即使我們建立了多個列表變數,只要它們指向同一個列表,更改該列表時它們也會全部更新,如下面的程式碼所示:
這是上面程式碼中實際發生的動畫的視覺化:
這解釋了為什麼在我們較早地嘗試使用列表和字典時更改了全域性變數的原因。由於列表和字典是可變的,因此更改它們(即使在函式內部)也將更改列表或字典本身,而對於不可變的資料型別則不是這種情況。
保持可變資料型別不變
一般來說,我們不希望函式更改全域性變數,即使它們包含諸如列表或字典之類的可變資料型別也是如此。那是因為在更復雜的分析和程式中,我們可能經常使用許多不同的功能。如果所有人都在更改他們正在處理的列表和詞典,則很難跟蹤正在更改的內容。
值得慶幸的是,有一個簡單的方法可以解決此問題:我們可以使用內建的Python方法來複制列表或字典.copy()。
如果您尚未了解方法,請不要擔心。它們在我們的Python中級課程中已涉及到,但是對於本教程而言,您需要知道的是它的.copy()工作方式如下.append():
讓我們再來看一下我們為列表編寫的函式,並對其進行更新,以使函式內部發生的變化不會改變initial_list。我們需要做的就是將傳遞給函式的引數從initial_list更改為initial_list.copy()
如我們所見,這解決了我們的問題。原因如下:using .copy()建立列表的單獨副本,因此指向initial_list自身的a_list是新副本,而不是指向自身initial_list。a_list之後,對該單獨的列表(而不是列表initial_list本身)進行的任何更改,因此的全域性值initial_list不變。
但是,該解決方案仍然不是完美的,因為.copy()每次傳遞引數給函式時,我們都必須記住要新增,否則就有可能意外更改的全域性值initial_list。如果我們不想為此擔心,我們實際上可以在函式內部建立該列表副本:
透過這種方法,我們可以像initial_list函式一樣安全地傳遞一個可變的全域性變數,並且不會更改全域性值,因為函式本身會建立一個副本,然後對該副本執行其操作。
該.copy()方法也適用於詞典。與列表一樣,我們可以簡單地新增.copy()引數到傳遞函式的位置,以建立一個副本,該副本將用於該函式,而無需更改原始變數:
但是,再次使用該方法意味著我們需要記住.copy() 每次將字典傳遞給make_percentages()函式時都要新增。如果我們要經常使用此函式,則最好將複製實現到函式本身中,這樣就不必記住這樣做了。
在下面,我們將.copy()在函式本身內部使用。這將確保我們可以在不更改作為引數傳遞給它的全域性變數的情況下使用它,並且無需記住要.copy()為傳遞的每個引數新增引數。
如我們所見,修改函式以建立字典的副本,然後僅在該副本中將計數更改為百分比已使我們能夠執行所需的操作,而無需實際更改content_ratings。
結論
在python函式控制列表和詞典中,我們研究了可變資料型別和可變資料型別之間的區別,可變資料型別可以更改,可變資料型別不能更改。我們瞭解瞭如何使用該方法.copy()製作可變資料型別(如列表和字典)的副本,以便我們可以在不更改其全域性值的情況下在函式中使用它們。
Python的函式(內建函式和我們自己編寫的自定義函式)是處理資料的關鍵工具。但是他們對資料的處理可能會有些混亂,如果我們不知道發生了什麼,可能會導致分析中的嚴重錯誤。
在python函式控制列表和詞典中,我們將仔細研究Python在函式內部進行操作時如何對待不同的資料型別,並學習如何確保僅在需要更改資料時才更改資料。
功能中的記憶體隔離
要了解Python如何處理函式內部的全域性變數,讓我們做一些實驗。我們將建立兩個全域性變數number_1和number_2,並將它們分配給整數5and 10。然後,我們將這些全域性變數用作執行一些簡單數學運算的函式中的引數。我們還將變數名用作函式的引數名。然後,我們將檢視函式內部的所有變數用法是否已影響這些變數的全域性值。
正如我們可以看到上面的功能工作正常,以及全球變數的值number_1,並number_2沒有不改變,即使我們用它們作為引數,並在我們的函式的引數名稱。這是因為Python將函式的變數儲存在與全域性變數不同的記憶體位置中。它們是孤立的。因此,變數number_1在全域性範圍內可以具有一個值(5),而在函式內部則可以具有不同的值(50),在此將其隔離。
列表和詞典呢?
清單
我們已經看到,對number_1函式內部的上述變數執行的操作不會影響其全域性值。但是number_1是一個整數,這是一個非常基本的資料型別。如果我們嘗試使用不同的資料型別(例如列表)進行相同的實驗,會發生什麼?在下面,我們將建立一個名為的函式duplicate_last(),該函式將在我們將其作為引數傳遞的任何列表中複製最終條目。
如我們所見,即使僅在函式中更改了全域性值,此處的全域性值也initial_list 已更新!
辭典
現在,讓我們編寫一個將字典作為引數的函式,以檢視在函式內部對全域性字典變數進行修改時是否也會對其進行修改。
為了使這一點更加現實,我們將使用Python基礎知識課程中AppleStore.csv使用的資料集中的資料(可在此處下載資料)。
在下面的程式碼段中,我們從一個字典開始,該字典包含資料集中每個年齡等級的應用程式數量的計數(因此,有4,433個應用程式的等級為“ 4 +”,987個應用程式的等級為“ 9+”,等等。) 。假設我們要為每個年齡等級計算一個百分比,這樣我們就可以瞭解到哪個年齡等級在App Store中最常見。
為此,我們將編寫一個名為的函式make_percentages(),該函式將字典作為引數並將計數轉換為百分比。我們需要從零開始計數,然後對字典中的每個值進行迭代,然後將它們新增到計數中,以便獲得評分的總數。然後,我們將再次遍歷字典,並對每個值進行一些數學運算以計算百分比。
在檢視輸出之前,讓我們快速回顧一下上面發生的事情。在將應用程式年齡分級的字典分配給變數後content_ratings,我們建立了一個名為的新函式make_percentages(),該函式帶有一個引數:a_dictionary。
為了圖什麼應用程式的比例下降到每一個年齡分級,我們需要知道應用程式的總數,所以我們先設定一個所謂的新的變數total,以0透過在每個鍵,然後迴圈a_dictionary,將它新增到total。
一旦完成,我們要做的就是a_dictionary再次迴圈遍歷,將每個條目除以總數,然後將結果乘以100。這將為我們提供帶有百分比的字典。
但是,當我們使用global content_ratings作為該新函式的引數時會發生什麼呢?
就像我們在列表中看到的一樣content_ratings,即使僅在make_percentages()我們建立的函式內部對其進行了修改,我們的全域性變數也已更改。
那麼,這裡到底發生了什麼?我們碰到了可變和不可變資料型別之間的差異。
可變和不可變資料型別
在Python中,資料型別可以是可變的(可變的)或不可變的(不變的)。儘管我們在Python入門中使用的大多數資料型別都是不可變的(包括整數,浮點數,字串,布林值和元組),但列表和字典卻是可變的。這意味著全域性列表或字典即使在函式內部使用時也可以更改,就像我們在上面的示例中看到的那樣。
要了解可變(可變)和不可變(不變)之間的區別,研究一下Python如何實際處理這些變數是有幫助的。
讓我們開始考慮一個簡單的變數賦值:
變數名的a作用類似於指向的指標5,它可以幫助我們5在需要時進行檢索。
5是整數,整數是不可變的資料型別。如果資料型別是不可變的,則意味著它一旦建立便無法更新。如果這樣做a += 1,我們實際上5並沒有更新到6。在下面的動畫中,我們可以看到:
1)a最初指向5。
2)a += 1執行,並將指標從5移到6,實際上並沒有改變number 5。
列表和字典等可變資料型別的行為有所不同。它們可以被更新。因此,例如,讓我們列出一個非常簡單的列表:
如果將a附加3到此列表的末尾,我們不僅會指向list_1其他列表,還會直接更新現有列表:
即使我們建立了多個列表變數,只要它們指向同一個列表,更改該列表時它們也會全部更新,如下面的程式碼所示:
這是上面程式碼中實際發生的動畫的視覺化:
這解釋了為什麼在我們較早地嘗試使用列表和字典時更改了全域性變數的原因。由於列表和字典是可變的,因此更改它們(即使在函式內部)也將更改列表或字典本身,而對於不可變的資料型別則不是這種情況。
保持可變資料型別不變
一般來說,我們不希望函式更改全域性變數,即使它們包含諸如列表或字典之類的可變資料型別也是如此。那是因為在更復雜的分析和程式中,我們可能經常使用許多不同的功能。如果所有人都在更改他們正在處理的列表和詞典,則很難跟蹤正在更改的內容。
值得慶幸的是,有一個簡單的方法可以解決此問題:我們可以使用內建的Python方法來複制列表或字典.copy()。
如果您尚未了解方法,請不要擔心。它們在我們的Python中級課程中已涉及到,但是對於本教程而言,您需要知道的是它的.copy()工作方式如下.append():
讓我們再來看一下我們為列表編寫的函式,並對其進行更新,以使函式內部發生的變化不會改變initial_list。我們需要做的就是將傳遞給函式的引數從initial_list更改為initial_list.copy()
如我們所見,這解決了我們的問題。原因如下:using .copy()建立列表的單獨副本,因此指向initial_list自身的a_list是新副本,而不是指向自身initial_list。a_list之後,對該單獨的列表(而不是列表initial_list本身)進行的任何更改,因此的全域性值initial_list不變。
但是,該解決方案仍然不是完美的,因為.copy()每次傳遞引數給函式時,我們都必須記住要新增,否則就有可能意外更改的全域性值initial_list。如果我們不想為此擔心,我們實際上可以在函式內部建立該列表副本:
透過這種方法,我們可以像initial_list函式一樣安全地傳遞一個可變的全域性變數,並且不會更改全域性值,因為函式本身會建立一個副本,然後對該副本執行其操作。
該.copy()方法也適用於詞典。與列表一樣,我們可以簡單地新增.copy()引數到傳遞函式的位置,以建立一個副本,該副本將用於該函式,而無需更改原始變數:
但是,再次使用該方法意味著我們需要記住.copy() 每次將字典傳遞給make_percentages()函式時都要新增。如果我們要經常使用此函式,則最好將複製實現到函式本身中,這樣就不必記住這樣做了。
在下面,我們將.copy()在函式本身內部使用。這將確保我們可以在不更改作為引數傳遞給它的全域性變數的情況下使用它,並且無需記住要.copy()為傳遞的每個引數新增引數。
如我們所見,修改函式以建立字典的副本,然後僅在該副本中將計數更改為百分比已使我們能夠執行所需的操作,而無需實際更改content_ratings。
結論
在python函式控制列表和詞典中,我們研究了可變資料型別和可變資料型別之間的區別,可變資料型別可以更改,可變資料型別不能更改。我們瞭解瞭如何使用該方法.copy()製作可變資料型別(如列表和字典)的副本,以便我們可以在不更改其全域性值的情況下在函式中使用它們。