一琼稻、可調(diào)用類(lèi)型
在 python中所有的類(lèi)型都是對(duì)象幻馁,即使是 int庇配,float這些其他語(yǔ)言中的基礎(chǔ)類(lèi)型在 python中也是以對(duì)象的形式存在尼夺,函數(shù)和方法也不例外尊残。
在 python中函數(shù)和方法是可調(diào)用類(lèi)型的兩個(gè)子集,可調(diào)用類(lèi)型一共有 5種:
類(lèi)型名稱(chēng) | 描述 |
---|---|
types.BuiltinFunctionType | 內(nèi)置函數(shù)或方法 |
type | 內(nèi)置類(lèi)型和類(lèi)的類(lèi)型 |
object | 所有類(lèi)和類(lèi)型的祖先 |
types.FunctionType | 用戶(hù)定義的函數(shù) |
types.MethodType | 類(lèi)方法 |
最后兩種就是我們常說(shuō)的函數(shù)和方法淤堵,函數(shù)在類(lèi)外被定義夜郁,而方法在類(lèi)里面被定義,我們也可以說(shuō)方法是類(lèi)里面的函數(shù)粘勒,如:
# 在類(lèi)外定義的是函數(shù)
def function_1():
print("Hello World. This is a function.")
class TestClass:
# 在類(lèi)里面定義的是方法
def function_2():
print("Hello World. This is a method.")
需要注意的是竞端,在 C++、JAVA這些面向?qū)ο蟮恼Z(yǔ)言中函數(shù)和方法指的是同一個(gè)概念庙睡,它們沒(méi)有像 python一樣做出類(lèi)型區(qū)分事富,只是在叫法上有些區(qū)別而已。
在這篇教程中我們只講函數(shù)乘陪,至于方法等我們講到類(lèi)的時(shí)候再詳細(xì)地講统台,在這之前大家像用函數(shù)一樣用方法就行。
二啡邑、函數(shù)的屬性
前面我們講到每個(gè)函數(shù)都是一個(gè)對(duì)象贱勃,對(duì)象自然有對(duì)應(yīng)的屬性:
-
__doc__
:函數(shù)的注釋?zhuān)褪蔷o挨著函數(shù)名的一個(gè)字符串,用來(lái)注釋函數(shù)谤逼,文檔生產(chǎn)工具可以根據(jù)這些字符串生成對(duì)應(yīng)的文檔贵扰,如:def f(name="name"): """ This is a function. """ pass print(f.__doc__) """ This is a function. """
-
__name__
:函數(shù)的名字,如:def function_name(): pass print(function_name.__name__) # function_name
-
__defaults__
:包含默認(rèn)參數(shù)名的元組流部,如:def function_defaults(args_1, args_2='name'): pass print(function_defaults.__defaults__) # ('name',)
三戚绕、函數(shù)的參數(shù)
函數(shù)的參數(shù)有兩種,位置參數(shù)和關(guān)鍵字參數(shù)枝冀,這兩者又分為有默認(rèn)值和沒(méi)有默認(rèn)值兩種類(lèi)型舞丛。
位置參數(shù)和關(guān)鍵字參數(shù)的主要區(qū)別是耘子,位置參數(shù)在傳遞的時(shí)候可以不指定變量名,而是按照約定的順序進(jìn)行賦值球切,而關(guān)鍵字參數(shù)必須指定變量名才能對(duì)其進(jìn)行賦值谷誓,如:
def function_args(a1, a2):
print("a1:", a1, "a2", a2)
function_args('1','2')
# a1: 1 a2 2
# a1和 a2都是位置參數(shù),第一個(gè)參數(shù)賦值給 a1吨凑,第二個(gè)參數(shù)賦值給 a2
def function_keyword_args(a1, *, a2):
print("a1:", a1, "a2", a2)
function_keyword_args('1', a2='2')
# 此時(shí)再使用 function_keyword_args('1', '2')會(huì)報(bào)錯(cuò)
# 因?yàn)?a2是關(guān)鍵字參數(shù)捍歪,必須指定變量名
所有的參數(shù)默認(rèn)為位置參數(shù),只有當(dāng)使用 *分隔時(shí)后面的參數(shù)才會(huì)被看作關(guān)鍵字參數(shù)怀骤。
注意:
在定義函數(shù)時(shí)上面四種參數(shù)的書(shū)寫(xiě)順序是有嚴(yán)格限制的费封,位置參數(shù)必須聲明在最前面焕妙,同時(shí)有默認(rèn)值的參數(shù)必須在沒(méi)有默認(rèn)值的參數(shù)后面蒋伦,如:
def function_args(a1, a2='2', *, a3, a4='4'):
print("a1:", a1, "a2", a2, "a3:", a3, "a4:", a4)
# 下面的定義是錯(cuò)誤的
# 有默認(rèn)值的參數(shù)在前
def function_args(a2='2', a1, *, a3, a4='4'):
print("a1:", a1, "a2", a2, "a3:", a3, "a4:", a4)
當(dāng)我們有很多參數(shù)要傳遞給函數(shù)時(shí),我們可能會(huì)寫(xiě)出這樣的代碼:
def function_args(a1, a2, a3, a4, a5, a6, *, b1, b2, b3, b4):
pass
function_args(1, 2, 3, 4, 5, 6, b1=1, b2=2, b3=3, b4=4)
這樣的代碼可以說(shuō)是很糟糕的代碼了焚鹊,這時(shí)我們可以使用 *
和 **
來(lái)簡(jiǎn)化我們的代碼痕届,如:
def function_args(a1, a2, a3, a4, a5, a6, *, b1, b2, b3, b4):
pass
args = [1, 2, 3, 4, 5, 6]
# 或者 args = (1, 2, 3, 4, 5, 6)
keyword_args = {
'b1': 1,
'b2': 2,
'b3': 3,
'b4': 4
}
function_args(*ags, **keyword_args)
*
的操作對(duì)象是列表或者元組,用來(lái)傳遞位置參數(shù)末患,**
的操作對(duì)象是字典研叫,用來(lái)傳遞關(guān)鍵字參數(shù)。
四璧针、函數(shù)作為變量使用
既然函數(shù)是一種特殊的變量類(lèi)型嚷炉,那變量所具有的操作肯定也可以應(yīng)用到函數(shù)上,比如:
-
賦值給其他變量:
def say_hello(): print("Hello World") say_hello_2 = say_hello say_hello_2() # Hello World
-
作為參數(shù)傳遞
def say_hello(): print("Hello World") def execute_func(func): func() execute_func(say_hello) # Hello World