python函數
- 函數名其實就是指向一個函數對象的引用,完全可以把函數名賦給一個變量,相當于給這個函數起了一個“別名”.
- 函數是可調用對象,可以使用內置函數
callable(obj)
,判斷對象是否可以調用 - python函數內沒有寫return語句時,默認執行完后返回一個空對象None。return None可以簡寫為return
a = type # 變量a指向type函數
a(1) # <class 'int'> ,所以也可以通過a調用type函數
callable(type) # True
函數返回多個值
- python的函數返回多個值,實際上就是返回一個tuple
def test():
return 1,2
test() # (1,2) 返回元組
常用內置函數
-
isinstance(obj, class_or_tuple, /)
# Return whether an object is an instance of a class or of a subclass thereof.
isinstance(1, int) # True
isinstance(1, (int, str)) # True,相當于isinstance(1, int) or isinstance(1, str)
-
callable(obj, /)
# Return whether the object is callable
函數的參數
- 在Python中定義函數,可以用位置參數或者說必選參數、默認參數、可變參數args、關鍵字參數*kwargs和命名關鍵字參數,這5種參數都可以組合使用。
- 參數定義的順序必須是:必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。
def test(a, b):
print(a, b)
test(1, 2) # 輸出:1 2,直接按順序傳遞位置參數
test(b=2, a=1) # 輸出:1 2,根據形參的名字來傳遞參數,可以不按順序
test(a=1, 3) # 報錯:位置參數必須第一
定義默認參數
- 定義默認參數要牢記一點:
默認參數必須指向不變對象!
- 下面是默認參數是可便對象時每一次傳遞默認參數返回的結果不一樣的例子
def add_end(L=[]):
L.append('END')
return L
add_end() # 第一次默認參數調用返回:['END']
add_end() # 第二次默認參數調用返回:['END', 'END']
add_end() # 第三次默認參數調用返回:['END', 'END', 'END']
- 原因解釋如下:
Python函數在定義的時候,默認參數L的值就被計算出來了,即[],因為默認參數L也是一個變量,它指向對象[],每次調用該函數,如果改變了L的內容,則下次調用時,默認參數的內容就變了,不再是函數定義時的[]了。
可變參數和關鍵字參數
-
可變參數*args
:可變參數允許傳入0個或任意個參數,這些可變參數在函數調用時自動組裝為一個tuple傳給形參。
# 所有條件都是True才返回True(a&b&c&...),用于解決需要多個skip條件
def is_all_true(a, *args)->bool:
result = bool(a)
for n in args:
result = result & bool(n)
return result
is_all_true(True, 1)
-
關鍵字參數**kwargs
:關鍵字參數允許你傳入0個或任意個含參數名的參數,這些關鍵字參數在函數內部自動組裝為一個dict傳給形參。
def test(a, **kwargs):
print(a, kwargs)
test(1) # 1 {}
test(1, name="a", age=28) # 1 {name="a", age=28}
-
命名關鍵字參數keyword-only
:python3引入,定義的時候是位置參數但是調用的時候必須使用關鍵字參數傳參。命名的關鍵字參數是為了限制調用者可以傳入的參數名
def test1(a, *, x, y): # x,y都變成keyword-only參數
print(a, x, y)
test1(1) # 報錯 missing 2 required keyword-only argument
test1(1, x=1, y=2) # 返回:1 1 2
def test2(*args, x, **kwargs): # x 即keyword-only參數
print(args, x,kwargs)
test2(1,2, x=3) # 返回: (1,2) 3 {}
參數組合
- 先滿足位置參數,再滿足默認參數,再滿足args或kw
def test(a, b=None, *args, **kw):
print(a,'--',b,'--',args,'--',kw)
test(1, "cc") # 1 -- cc -- () -- {}
test(1, "cc", "cc") # 1 -- cc -- ('cc',)
test(1, b="cc") # 1 -- cc -- () -- {},b="cc"會傳遞給默認參數b而不是kw
test(1, c="cc") # 1 -- None -- () -- {'c': 'cc'}
test(1, b="cc", c="cc") # 1--cc--()--{'c': 'cc'}
test(1, b="cc", "cc") # 報錯:SyntaxError: positional argument follows keyword argument
test(1, "cc", "cc") # 1 -- cc -- ('cc',) -- {}
test(1, "cc", c="cc") # 1--cc--()--{'c': 'cc'}
python不需要函數重載
- 函數重載override:當兩個函數除了 參數類型和參數個數不同 外,其函數名稱和功能完全相同,此時才使用函數重載。
- python函數不需要解決函數重載的兩個問題: 對于可變參數類型,python可以接受任意類型的參數;對于可變參數個數,python可以使用缺省參數。
函數注釋
函數注釋:python3新增特性,定義函數的時候可以為函數添加參數注釋和返回值注釋。
- 參數注釋: type類型/str類型/dict類型,格式:
func(參數: 參數注解)
- 返回值注釋: type類型/str類型/dict類型,格式:
func()->返回值注解:
-
函數名.__annotations__
,返回函數的注解,dict類型
def sum(a: int, b: dict(type=int, help='arg b', c: 'arg c'))->int:
return a+b
# 參數a的注解值類型為 type , b 為 dict, c 為 str
sum.__annotations__
# {'a': <class 'int'>, b: {'type': <class 'int'>, 'help': 'arg b'}, 'c': 'arg c', 'return': <class 'int'>}
注意:
type=int, 返回{'type': <class 'int'>}
,type='int', 返回的是{'type': 'int'}
由于函數注釋是dict類型,是可變的,所以可以在程序運行時動態的增加注釋
def sum(a: dict(type=int), b: int)->dict(type=dict, help='return value'):
sum.__annotations__['a']['help'] = 'arg a' # 調用函數時,動態增加參數a的注釋
return a+b
sum(1, 2)
print(sum.__annotations__['a']) # {'type': <class 'int'>, 'help': 'arg a'}