❶ python的函數和參數
parameter 是函數定義的參數形式
argument 是函數調用時傳入的參數實體。
對於函數調用的傳參模式,一般有兩種:
此外,
也是關鍵字傳參
python的函數參數定義一般來說有五種: 位置和關鍵字參數混合 , 僅位置參數 , 僅關鍵字參數 , 可變位置參數 , 可變關鍵字參數 。其中僅位置參數的方式僅僅是一個概念,python語法中暫時沒有這樣的設計。
通常我們見到的函數是位置和關鍵字混合的方式。
既可以用關鍵字又可以用位置調用
或
這種方式的定義只能使用關鍵字傳參的模式
f(*some_list) 與 f(arg1, arg2, ...) (其中some_list = [arg1, arg2, ...])是等價的
網路模塊request的request方法的設計
多數的可選參數被設計成可變關鍵字參數
有多種方法能夠為函數定義輸出:
非常晦澀
如果使用可變對象作為函數的默認參數,會導致默認參數在所有的函數調用中被共享。
例子1:
addItem方法的data設計了一個默認參數,使用不當會造成默認參數被共享。
python裡面,函數的默認參數被存在__default__屬性中,這是一個元組類型
例子2:
在例子1中,默認參數是一個列表,它是mutable的數據類型,當它寫進 __defauts__屬性中時,函數addItem的操作並不會改變它的id,相當於 __defauts__只是保存了data的引用,對於它的內存數據並不關心,每次調用addItem,都可以修改 addItem.__defauts__中的數據,它是一個共享數據。
如果默認參數是一個imutable類型,情況將會不一樣,你無法改變默認參數第一次存入的值。
例子1中,連續調用addItem('world') 的結果會是
而不是期望的
❷ Python函數的參數類型
Python函數的參數類型主要包括必選參數、可選參數、可變參數、位置參數和關鍵字參數,本文介紹一下他們的定義以及可變數據類型參數傳遞需要注意的地方。
必選參數(Required arguments)是必須輸入的參數,比如下面的代碼,必須輸入2個參數,否則就會報錯:
其實上面例子中的參數 num1和num2也屬於關鍵字參數,比如可以通過如下方式調用:
執行結果:
可選參數(Optional arguments)可以不用傳入函數,有一個默認值,如果沒有傳入會使用默認值,不會報錯。
位置參數(positional arguments)根據其在函數定義中的位置調用,下面是pow()函數的幫助信息:
x,y,z三個參數的的順序是固定的,並且不能使用關鍵字:
輸出:
在上面的pow()函數幫助信息中可以看到位置參數後面加了一個反斜杠 / ,這是python內置函數的語法定義,Python開發人員不能在python3.8版本之前的代碼中使用此語法。但python3.0到3.7版本可以使用如下方式定義位置參數:
星號前面的參數為位置參數或者關鍵字參數,星號後面是強制關鍵字參數,具體介紹見強制關鍵字參數。
python3.8版本引入了強制位置參數(Positional-Only Parameters),也就是我們可以使用反斜杠 / 語法來定義位置參數了,可以寫成如下形式:
來看下面的例子:
python3.8運行:
不能使用關鍵字參數形式賦值了。
可變參數 (varargs argument) 就是傳入的參數個數是可變的,可以是0-n個,使用星號( * )將輸入參數自動組裝為一個元組(tuple):
執行結果:
關鍵字參數(keyword argument)允許將任意個含參數名的參數導入到python函數中,使用雙星號( ** ),在函數內部自動組裝為一個字典。
執行結果:
上面介紹的參數可以混合使用:
結果:
注意:由於傳入的參數個數不定,所以當與普通參數一同使用時,必須把帶星號的參數放在最後。
強制關鍵字參數(Keyword-Only Arguments)是python3引入的特性,可參考:https://www.python.org/dev/peps/pep-3102/。 使用一個星號隔開:
在位置參數一節介紹過星號前面的參數可以是位置參數和關鍵字參數。星號後面的參數都是強制關鍵字參數,必須以指定參數名的方式傳參,如果強制關鍵字參數沒有設置默認參數,調用函數時必須傳參。
執行結果:
也可以在可變參數後面命名關鍵字參數,這樣就不需要星號分隔符了:
執行結果:
在Python對象及內存管理機制中介紹了python中的參數傳遞屬於對象的 引用傳遞 (pass by object reference),在編寫函數的時候需要特別注意。
先來看個例子:
執行結果:
l1 和 l2指向相同的地址,由於列表可變,l1改變時,l2也跟著變了。
接著看下面的例子:
結果:
l1沒有變化!為什麼不是[1, 2, 3, 4]呢?
l = l + [4]表示創建一個「末尾加入元素 4「的新列表,並讓 l 指向這個新的對象,l1沒有進行任何操作,因此 l1 的值不變。如果要改變l1的值,需要加一個返回值:
結果:
下面的代碼執行結果又是什麼呢?
執行結果:
和第一個例子一樣,l1 和 l2指向相同的地址,所以會一起改變。這個問題怎麼解決呢?
可以使用下面的方式:
也可以使用淺拷貝或者深度拷貝,具體使用方法可參考Python對象及內存管理機制。這個問題在Python編程時需要特別注意。
本文主要介紹了python函數的幾種參數類型:必選參數、可選參數、可變參數、位置參數、強制位置參數、關鍵字參數、強制關鍵字參數,注意他們不是完全獨立的,比如必選參數、可選參數也可以是關鍵字參數,位置參數可以是必選參數或者可選參數。
另外,python中的參數傳遞屬於對象的 引用傳遞 ,在對可變數據類型進行參數傳遞時需要特別注意,如有必要,使用python的拷貝方法。
參考文檔:
--THE END--
❸ Python中的10條冷門知識
下面時Python中一些不常見的冷門知識,感興趣的小夥伴不妨來學習一下。
1、省略號也是對象
… 這是省略號,在Python中,一切皆對象。它也不例外。在 Python 中,它叫做 Ellipsis 。在 Python 3 中你可以直接寫…來得到這玩意。
>>> ...
Ellipsis
>>> type(...)
<class 'ellipsis'>
而在 Python2 中沒有…這個語法,只能直接寫Ellipsis來獲取。
>>> Ellipsis
Ellipsis
>>> type(Ellipsis)
<type 'ellipsis'>
它轉為布爾值時為真
>>> bool(...)
True
最後,這東西是一個單例。
>>> id(...)
4362672336
>>> id(...)
4362672336
這東西有啥用呢?據說它是Numpy的語法糖,不玩 Numpy 的人,可以說是沒啥用的。
在網上只看到這個 用 … 代替 pass ,稍微有點用,但又不是必須使用的。
try:
1/0
except ZeroDivisionError:
...
2、增量賦值的性能更好
諸如 += 和 *= 這些運算符,叫做 增量賦值運算符。這里使用用 += 舉例,以下兩種寫法,在效果上是等價的。
# 第一種
a = 1 ; a += 1
# 第二種
a = 1; a = a + 1
+= 其背後使用的魔法方法是 iadd,如果沒有實現這個方法則會退而求其次,使用 add 。
這兩種寫法有什麼區別呢?
用列表舉例 a += b,使用 add 的話就像是使用了a.extend(b),如果使用 add 的話,則是 a = a+b,前者是直接在原列表上進行擴展,而後者是先從原列表中取出值,在一個新的列表中進行擴展,然後再將新的列表對象返回給變數,顯然後者的消耗要大些。
所以在能使用增量賦值的時候盡量使用它。
3、and 和or 的取值順序
and 和 or 是我們再熟悉不過的兩個邏輯運算符。而我們通常只用它來做判斷,很少用它來取值。
如果一個or表達式中所有值都為真,Python會選擇第一個值,而and表達式則會選擇第二個。
>>>(2 or 3) * (5 and 7)
14 # 2*7
4、修改解釋器提示符
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>>
>>> sys.ps2 = '---------------- '
>>> sys.ps1 = 'Python編程時光>>>'
Python編程時光>>>for i in range(2):
---------------- print (i)
----------------
5、默認參數最好不為可變對象
函數的參數分三種
可變參數
默認參數
關鍵字參數
今天要說的是,傳遞默認參數時,新手很容易踩雷的一個坑。
先來看一個示例:
def func(item, item_list=[]):
item_list.append(item)
print(item_list)
func('iphone')
func('xiaomi', item_list=['oppo','vivo'])
func('huawei')
在這里,你可以暫停一下,思考一下會輸出什麼?
思考過後,你的答案是否和下面的一致呢
['iphone']
['oppo', 'vivo', 'xiaomi']
['iphone', 'huawei']
如果是,那你可以跳過這部分內容,如果不是,請接著往下看,這里來分析一下。
Python 中的 def 語句在每次執行的時候都初始化一個函數對象,這個函數對象就是我們要調用的函數,可以把它當成一個一般的對象,只不過這個對象擁有一個可執行的方法和部分屬性。
對於參數中提供了初始值的參數,由於 Python 中的函數參數傳遞的是對象,也可以認為是傳地址,在第一次初始化 def 的時候,會先生成這個可變對象的內存地址,然後將這個默認參數 item_list 會與這個內存地址綁定。在後面的函數調用中,如果調用方指定了新的默認值,就會將原來的默認值覆蓋。如果調用方沒有指定新的默認值,那就會使用原來的默認值。
在這里插入圖片描述
6、訪問類中的私有方法
大家都知道,類中可供直接調用的方法,只有公有方法(protected類型的方法也可以,但是不建議)。也就是說,類的私有方法是無法直接調用的。
這里先看一下例子
class Kls():
def public(self):
print('Hello public world!')
def __private(self):
print('Hello private world!')
def call_private(self):
self.__private()
ins = Kls()
# 調用公有方法,沒問題
ins.public()
# 直接調用私有方法,不行
ins.__private()
# 但你可以通過內部公有方法,進行代理
ins.call_private()
既然都是方法,那我們真的沒有方法可以直接調用嗎?
當然有啦,只是建議你千萬不要這樣弄,這里只是普及,讓你了解一下。
# 調用私有方法,以下兩種等價
ins._Kls__private()
ins.call_private()
7、時有時無的切片異常
這是個簡單例子
my_list = [1, 2, 3, 4, 5]
print(my_list[5])
Traceback (most recent call last):
File "F:/Python Script/test.py", line 2, in <mole>
print(my_list[5])
IndexError: list index out of range
來看看,如下這種寫法就不會報索引異常,執行my_list[5:],會返回一個新list:[]。
my_list = [1, 2, 3]
print(my_list[5:])
8、for 死循環
for 循環可以說是 基礎得不能再基礎的知識點了。但是如果讓你用 for 寫一個死循環,你會寫嗎?(問題來自群友 陳**)
這是個開放性的問題,在往下看之前,建議你先嘗試自己思考,你會如何解答。
好了,如果你還沒有思路,那就來看一下 一個海外 MIT 群友的回答:
for i in iter(int, 1):pass
是不是懵逼了。iter 還有這種用法?這為啥是個死循環?
這真的是個冷知識,關於這個知識點,你如果看中文網站,可能找不到相關資料。
還好你可以通過 IDE 看py源碼里的注釋內容,介紹了很詳細的使用方法。
原來iter有兩種使用方法,通常我們的認知是第一種,將一個列表轉化為一個迭代器。
而第二種方法,他接收一個 callable對象,和一個sentinel 參數。第一個對象會一直運行,直到它返回 sentinel 值才結束。
在這里插入圖片描述
那int 呢,這又是一個知識點,int 是一個內建方法。通過看注釋,可以看出它是有默認值0的。你可以在終端上輸入 int() 看看是不是返回0。
在這里插入圖片描述
由於int() 永遠返回0,永遠返回不了1,所以這個 for 循環會沒有終點。一直運行下去。
9、奇怪的字元串
字元串類型作為 Python 中最常用的數據類型之一,Python解釋器為了提高字元串使用的效率和使用性能,做了很多優化。
例如:Python 解釋器中使用了 intern(字元串駐留)的技術來提高字元串效率。
什麼是 intern 機制?就是同樣的字元串對象僅僅會保存一份,放在一個字元串儲蓄池中,是共用的,當然,肯定不能改變,這也決定了字元串必須是不可變對象。
示例一
# Python2.7
>>> a = "Hello_Python"
>>> id(a)
32045616
>>> id("Hello" + "_" + "Python")
32045616
# Python3.7
>>> a = "Hello_Python"
>>> id(a)
38764272
>>> id("Hello" + "_" + "Python")
32045616
示例二
>>> a = "MING"
>>> b = "MING"
>>> a is b
True
# Python2.7
>>> a, b = "MING!", "MING!"
>>> a is b
True
# Python3.7
>>> a, b = "MING!", "MING!"
>>> a is b
False
示例三
# Python2.7
>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
True
>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
False
# Python3.7
>>> 'a' * 20 is 'aaaaaaaaaaaaaaaaaaaa'
True
>>> 'a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa'
True
示例四
>>> s1="hello"
>>> s2="hello"
>>> s1 is s2
True
# 如果有空格,默認不啟用intern機制
>>> s1="hell o"
>>> s2="hell o"
>>> s1 is s2
False
# 如果一個字元串長度超過20個字元,不啟動intern機制
>>> s1 = "a" * 20
>>> s2 = "a" * 20
>>> s1 is s2
True
>>> s1 = "a" * 21
>>> s2 = "a" * 21
>>> s1 is s2
False
>>> s1 = "ab" * 10
>>> s2 = "ab" * 10
>>> s1 is s2
True
>>> s1 = "ab" * 11
>>> s2 = "ab" * 11
>>> s1 is s2
False
10、兩次return
我們都知道,try…finally… 語句的用法,不管 try 裡面是正常執行還是報異常,最終都能保證finally能夠執行。
同時,我們又知道,一個函數里只要遇到 return 函數就會立馬結束。
基於以上這兩點,我們來看看這個例子,到底運行過程是怎麼樣的?
>>> def func():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> func()
'finally'
驚奇的發現,在try里的return居然不起作用。
原因是,在try…finally…語句中,try中的return會被直接忽視,因為要保證finally能夠執行。
❹ 簡單談談Python中函數的可變參數
簡單談談Python中函數的可變參數
在Python中定義函數,可以用必選參數、默認參數、可變參數和關鍵字參數,這4種參數都可以一起使用,或者只用其中某些,但是請注意,參數定義的順序必須是:必選參數、默認參數、可變參數和關鍵字參數。
可變參數( * )
可變參數,顧名思義,它的參數是可變的,比如列表、字典等。如果我們需要函數處理可變數量參數的時候,就可以使用可變參數。
我們在查看很多Python源碼時,經常會看到 某函數(*參數1, **參數2)這樣的函數定義,這個*參數和**參數就是可變參數,一時會讓人有點費解。其實只要把函數可變參數的定義搞清楚了,就不難理解了。
當我們不知道需要用幾個參數來定義函數的時候,可變參數就可以大展手腳了。
在Python里,帶 * 的參數就是用來接受可變數量參數的。
如果一個函數定義如下:
def functionTest(*args):
....
....
....
調用時我們可以的這樣調用:
functionTest(1)
或者
functionTest(1,2)
或者
functionTest(1,2,3)
後面可以傳入多個參數。
看段實例代碼,觀察下*是怎麼具體應用的吧:
def get_sum(*numbers):
sum = 0
for n in numbers:
sum += n
return sum
#在這里寫下你的代碼來調用get_sum來求5個數字的和,並輸出這個結果
print (get_sum(1,2,3,4,5))
結果會是什麼呢?大家可以自己動手操作起來看下,以就是關於Python中函數可變參數的全部內容,希望這篇文章對大家學習或使用python能有所幫助
❺ python可變參數求和
在Python函數中,還可以定義可變參數。顧名思義,可變參數就是傳入的參數個數是可變的,可以是1個、2個到任意個,還可以是0個。
我們以數學題為例子,給定一組數字a,b,c……,請計算a^2 + b^2 + c^2 + ……。
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
定義可變參數和定義一個list或tuple參數相比,僅僅在參數前面加了一個*號。在函數內部,參數numbers接收到的是一個tuple,因此,函數代碼完全不變。但是,調用該函數時,可以傳入任意個參數,包括0個參數:
>>> calc(1, 2)
5
>>> calc()
0
❻ python 默認參數 和 可變參數
參數傳遞的事了。
rol("hello",*args)這裡面*args可以解壓,就是把列表打散,然後復制給函數,當然函數裡面也有*args,所以又生成了一個tuple。
下面的輸出結果跟你的一樣。注意星號的用法。