關於Python中包裹傳參和解包裹的理解
1.包裹傳參
首先思考一個問題:為什麼要有包裹傳參?原因包括但不僅限於以下兩點:①不確定引數的個數。②希望函式定義的更加鬆散靈活
包裹傳參分兩種:包裹位置傳參和包裹關鍵字傳參。先看包裹位置傳參:
在這裡,如果先說定義肯定有些晦澀難懂,我們直接看下面這個例子吧!
1 def package_position(*all_arguments): 2print(type(all_arguments)) 3print(all_arguments)
這裡定義了一個函式package_position(),其傳入引數與一般的引數不一樣,前面有一個*號,表明這是一個包裹,接下來呼叫的時候如下:
1 package_position(1, 4, 6) 2 package_position(5, 6, 7, 1, 2, 3)
那麼列印的結果呢,是這樣的:
根據函式的定義,我們知道,列印的第一行是傳入的引數的型別(即type),根據列印結果,我們知道這是一個tuple,即元祖型別。也就是說,當我們在呼叫這個方法的時候,傳入的引數1,4,6,最後全部包在一起,封裝成一個tuple,傳遞給函式內部。列印的第二行,就是該元祖的內容。然後,根據列印結果的第二行,我們可以知道,這就是我們在呼叫時傳入的1,4,6。
總結一下:在呼叫package_position()時,所有的資料都根據先後順序,收集到一個元祖,在函式內部,我們可以通過元祖來讀取傳入的資料,這就是包裹位置傳參。
再來看看什麼時包裹關鍵字傳參:
有了以上包裹位置傳參,那麼包裹關鍵字傳參就不多說了,還是直接看例子:
1 def package_keyword(**all_arguments): 2print(type(all_arguments)) 3print(all_arguments) 4 5 package_keyword(a = 1, b = 9) 6 package_keyword(m = 2, n = 1, c = 11)
與上面一個例子類似,當函式呼叫時,所有引數會收集到一個數據容器裡。只不過,在包裹關鍵字傳遞的時候,,資料容器不再是一個元祖,而時一個字典。每個關鍵字形式的引數呼叫,都會成為字典的一個元素。引數名為元素的鍵,而資料成為元素的值。字典all_arguments收集了所有的引數,把資料傳遞給函式使用。為了提醒,引數all_arguments是包裹關鍵字傳遞所有的字典,因此在all_arguments前加**。列印結果如下:
2.解包裹
除了用於函式定義,*和**還可用於函式呼叫。這時候,兩者是為了實現一種叫作解包裹(unpacking)的語法。解包裹允許我們把一個數據容器傳遞給函式,再自動地分解為各個引數。需要注意的是,包裹傳參和解包裹並不是相反操作,而是兩個相對獨立的功能(但給人的感覺就是兩個相反的操作)。下面是解包裹的一個例子:
1 def unpackage(a, b, c): 2print(a, b, c) 3 4 args = (1, 3, 4) 5 unpackage(*args) 6 7 args = {"a":1, "b":2, "c":3} 8 unpackage(**args)
根據上面的程式碼,估計讀者也大概知道了關於解包裹的概念。我們呼叫函式時傳遞的是一個元祖,按照基本傳參的方式,一個元祖是無法和三個引數對應上的。但我們通過在args前加上*符號,來提醒Python,我想把元祖拆成三個元素,每一個元素對應函式的一個位置引數。於是,元祖的三個元素分別賦予了三個引數。
相應的,詞典也可用於解包裹(上述程式碼第7,8行)。在傳遞詞典args時,讓詞典的每個鍵值對作為一個關鍵字傳遞給函式。