1. 程式人生 > >Python知識點——“==”和“is”和“*”和“**”

Python知識點——“==”和“is”和“*”和“**”

1:python中的“ ==” 與“ is”的區別,不嚴謹得說,“ ==”比較值,“ is”比較記憶體地址。但是注意,python的垃圾回收機制決定【-5,256】之間的資料不會重建為另外一份,因此這些資料的“ ==” 與“ is”是等價的。而字串的比較,則是比較其記憶體地址,如果要修改為比較值,應對運算子__eq__進行過載,詳情參見:https://blog.csdn.net/kobebryantlin0/article/details/73391584

2:剛學用Python的時候,特別是看一些庫的原始碼時,經常會看到func(*args, **kwargs)這樣的函式定義,這個*和**讓人有點費解。其實只要把函式引數定義搞清楚了,就不難理解了。
先說說函式定義,我們都知道,下面的程式碼定義了一個函式funcA
def funcA():
pass

顯然,函式funcA沒有引數(同時啥也不幹:D)。
下面這個函式funcB就有兩個引數了,
def funcB(a, b):
print a
print b
呼叫的時候,我們需要使用函式名,加上圓括號擴起來的引數列表,比如 funcB(100, 99),執行結果是:
100
99
很明顯,引數的順序和個數要和函式定義中一致,如果執行funcB(100),Python會報錯的:
TypeError: funcB() takes exactly 2 arguments (1 given)
我們可以在函式定義中使用引數預設值,比如
def funcC(a, b=0):
print a
print b
在函式funcC的定義中,引數b有預設值,是一個可選引數,如果我們呼叫funcC(100),b會自動賦值為0。
OK,目前為止,我們要定義一個函式的時候,必須要預先定義這個函式需要多少個引數(或者說可以接受多少個引數)。一般情況下這是沒問題的,但是也有在定義函式的時候,不能知道引數個數的情況(想一想C語言裡的printf函式),在Python裡,帶*的引數就是用來接受可變數量引數的。看一個例子
def funcD(a, b, *c):
print a
print b
print "length of c is: %d " % len(c)
print c
呼叫funcD(1, 2, 3, 4, 5, 6)結果是
1
2
length of c is: 4
(3, 4, 5, 6)
我們看到,前面兩個引數被a、b接受了,剩下的4個引數,全部被c接受了,c在這裡是一個tuple。我們在呼叫funcD的時候,至少要傳遞2個引數,2個以上的引數,都放到c裡了,如果只有兩個引數,那麼c就是一個empty tuple。
好了,一顆星我們弄清楚了,下面輪到兩顆星。
上面的例子裡,呼叫函式的時候,傳遞的引數都是根據位置來跟函式定義裡的引數表匹配的,比如funcB(100, 99)和funcB(99, 100)的執行結果是不一樣的。在Python裡,還支援一種用關鍵字引數(keyword argument)呼叫函式的辦法,也就是在呼叫函式的時候,明確指定引數值付給那個形參。比如還是上面的funcB(a, b),我們通過這兩種方式呼叫
funcB(a=100, b=99)

funcB(b=99, a=100)
結果跟funcB(100, 99)都是一樣的,因為我們在使用關鍵字引數呼叫的時候,指定了把100賦值給a,99賦值給b。也就是說,關鍵字引數可以讓我們在呼叫函式的時候打亂引數傳遞的順序!
另外,在函式呼叫中,可以混合使用基於位置匹配的引數和關鍵字引數,前題是先給出固定位置的引數,比如
def funcE(a, b, c):
print a
print b
print c
呼叫funcE(100, 99, 98)和呼叫funcE(100, c=98, b=99)的結果是一樣的。
好了,經過以上鋪墊,兩顆星總算可以出場了:
如果一個函式定義中的最後一個形參有 ** (雙星號)字首,所有正常形參之外的其他的關鍵字引數都將被放置在一個字典中傳遞給函式,比如:
def funcF(a, **b):
print a
for x in b:
print x + ": " + str(b[x])
呼叫funcF(100, c='你好', b=200),執行結果
100
c: 你好
b: 200
大家可以看到,b是一個dict物件例項,它接受了關鍵字引數b和c。