Python 極簡教程(十八)函數(shù)(2)參數(shù)

我們在編寫代碼時酌住,如果要調(diào)用別人寫的函數(shù)偶房,一般我們不需要關(guān)心這些函數(shù)是如何實現(xiàn)的听绳,只需要關(guān)注如何使用這個函數(shù)。
那么怎么才能知道如何使用呢邀层?也就是我們必須要知道這個函數(shù)需要哪些參數(shù)返敬,參數(shù)都代表什么,哪些參數(shù)是必須寫的寥院,哪些是不用管的劲赠,最后關(guān)注其返回的結(jié)果如何,這樣就能正確的使用該函數(shù)秸谢。

比如我們前面講過的range函數(shù):

range(10)
range(1,10)
range(1, 10, 2)

我們看在傳參數(shù)的時候凛澎,數(shù)量不同會得到不同的結(jié)果。其實這就是 Python 在函數(shù)定義的時候提供的各種參數(shù)形式估蹄。這種形式非常靈活塑煎,且功能強大。

在 Python 中臭蚁,有多種參數(shù)形式最铁,分別是位置參數(shù)(必選參數(shù)),默認(rèn)參數(shù)垮兑,可變參數(shù)和關(guān)鍵字參數(shù)(不同的教程叫法不太一樣)冷尉。

位置參數(shù)

也叫做必選參數(shù),也就是說在函數(shù)定義的時候聲明的參數(shù)系枪,在調(diào)用的時候就必須全部給予實參雀哨,并且必須按照參數(shù)定義的順序賦值。

比如下例嗤无,我們都知道求圓的面積和周長必須要用到 半徑 r 和圓周率 π 震束,現(xiàn)在實現(xiàn)一個函數(shù),提供半徑 r 和 圓周率 π当犯,返回面積(πr2)和周長(2πr)

def circle(r, pi):
    area = pi * r ** 2
    perimeter = 2 * pi * r
    return area, perimeter

當(dāng)我們調(diào)用 circle() 函數(shù)的時候垢村,必須同時提供 r 和 π 兩個參數(shù),否則就會報錯嚎卫,當(dāng)然多了也不行嘉栓。

>>> circle(4)
TypeError: circle() missing 1 required positional argument: 'pi'

也就是說參數(shù)不能多也不能少,必須按照函數(shù)定義的參數(shù)個數(shù)依次賦值拓诸,才能正常調(diào)用該函數(shù)侵佃。

>>> circle(4, 3.14)
(50.24, 25.12)

如果順序反了就得不到你想到的結(jié)果了!

>>> circle(3.14, 4)
(39.4384, 25.12)

如果你非要反著用(不按順序),請使用 參數(shù)名=參數(shù)值 的形式奠支。

>>> circle(pi=3.14, r=4)
(50.24, 25.12)

對于沒有任何標(biāo)識的參數(shù)馋辈,我們就稱之為 位置參數(shù)

默認(rèn)參數(shù)

剛才的 circle() 函數(shù),我們在用的時候必須同時傳入 r 和 π 兩個參數(shù)倍谜。但是我們發(fā)現(xiàn) π 也就是圓周率迈螟,一般都是固定的用兩位小數(shù) 3.14。

那么我們就沒必要每次調(diào)用這個函數(shù)都要輸這個 π尔崔,畢竟圓周率不是誰想改就能改的答毫。但是偶爾我們需要使用小數(shù)點后面 4 位或者 6 位以求得更精確的面積和周長。那么如何實現(xiàn)呢季春?

對于函數(shù)的參數(shù)洗搂,絕大部分情況使用固定的值,在少數(shù)情況需要改該參數(shù)的值载弄,那么我們可以設(shè)置為默認(rèn)參數(shù)

簡而言之耘拇,就是給參數(shù)賦一個默認(rèn)值。這樣當(dāng)我們沒有特殊需要的時候侦锯,該參數(shù)直接用默認(rèn)值驼鞭,而當(dāng)你有特殊需要的時候,又可以通過提供新的值來實現(xiàn)你的需求尺碰。而且當(dāng)你沒有特殊需要的時候挣棕,還可以少傳一個參數(shù),使用起來更方便亲桥。

我們來改造一下上面的 circle() 函數(shù):

def circle(r, pi=3.14):     # 給參數(shù)賦一個默認(rèn)值即可
    area = pi * r ** 2
    perimeter = 2 * pi * r
    return area, perimeter

那么我們調(diào)用改造后的函數(shù):

# 沒有特殊需要的時候
>>> circle(4)
(50.24, 25.12)

# 精度要求更高的時候
>>> circle(4, 3.14159265358)
(50.26548245728, 25.13274122864)

是不是很方便洛心!

靈活使用默認(rèn)參數(shù),會大大增加函數(shù)調(diào)用者的體驗 :】

可變參數(shù)

參數(shù)收集

在某些情況下题篷,我們需要輸入不確定數(shù)量的參數(shù)(其實一般初級編程用不上)词身,那么根據(jù)上面我們說的參數(shù)必須按照順序和個數(shù)傳入,那么這種情況要怎么處理呢番枚?

在 Python 中提供了參數(shù)收集的機制法严,在函數(shù)定義時损敷,指定可變參數(shù)(參數(shù)收集),在函數(shù)調(diào)用的時候就可以提供任意數(shù)量的參數(shù)深啤。

比如拗馒,我們要寫一個函數(shù),用于保存任意多的用戶姓名:

def collect_names(*name):
  print('收集到的姓名:', name)

沒錯溯街,就是在參數(shù)前面加個星號*诱桂,在函數(shù)內(nèi)部使用這個參數(shù)即可。我們看看結(jié)果是什么呈昔?

>>> collect_names('nemo', 'nano', 'tato', 'jim', 'kid')   # 你想傳多少都可以挥等!
收集到的姓名: ('nemo', 'nano', 'tato', 'jim', 'kid')

從結(jié)果我們可以看出,通過參數(shù)收集到的任意參數(shù)堤尾,傳入函數(shù)內(nèi)部就變成了一個元組肝劲,元組嘛,當(dāng)然可以存任意多的數(shù)據(jù)了郭宝。

當(dāng)然收集到元組如何用涡相,就看你的需求了!

除了上面的直接收集參數(shù)的形式剩蟀,還有一種收集 參數(shù)名=參數(shù)值的傳參形式催蝗,而通過這種方式收集到的參數(shù)在內(nèi)部構(gòu)成一個字典。

如下例育特,寫一個函數(shù)丙号,收集一個人的信息。

def person(**attr):
  print('用戶的信息:', attr)

調(diào)用的結(jié)果:

>>> person(name='nemo', age=18, sex='男', height=180)
用戶的信息: {'name': 'nemo', 'age': 18, 'sex': '男', 'height': 180}

收集到內(nèi)部形成一個字典缰冤,然后你要操作就隨你咯犬缨。比如:

def person(**attr):
  for k in attr.keys():
    print('用戶的%s信息:%s' % (k, attr.get(k)))

>>> person(name='nemo', age=18, sex='男', height=180)
用戶的name信息:nemo
用戶的age信息:18
用戶的sex信息:男
用戶的height信息:180

也就是說你收集到了用戶的信息后,根據(jù)你的需要從字典中提取數(shù)據(jù)并處理棉浸。

參數(shù)收集的逆向過程

其實上面講的參數(shù)收集怀薛,在你日常編碼過程中使用相對較少,反倒其逆向過程用得更多迷郑。
那什么是參數(shù)收集的逆向過程呢枝恋?

參數(shù)收集是在函數(shù)調(diào)用時,傳入任意多的參數(shù)嗡害,在函數(shù)內(nèi)部形式一個元組或字典焚碌。而逆向過程,是先有一個元組(或任意序列)或字典霸妹,在函數(shù)調(diào)用時傳入該序列或字典十电。

那么這有何用處呢?可以簡化函數(shù)調(diào)用,并增加函數(shù)的可讀性鹃骂。
首先我們看第一種參數(shù)收集的逆向過程(元組):
比如用上面的 circle 函數(shù)的例子台盯,我們在一個數(shù)據(jù)文件中存儲了多個需要求面積和周長的數(shù)據(jù)。然后提取出來后放在一個二維的元組中畏线,我們需要調(diào)用該函數(shù)逐一運算爷恳。代碼如下:

data = ((4, 3.14), (6, 3.1415), (11, 3.14))
for i in data:
  circle(i[0], i[1])

好在我們這里只有兩個參數(shù),如果參數(shù)更多一些象踊,比如5個6個,那么你要怎么寫 fun(i[0], i[1], i[2]....)編不下去了棚壁。杯矩。。急需一個更簡單方便的方式袖外,正好史隆。。曼验。

data = ((4, 3.14), (6, 3.1415), (11, 3.14))
for i in data:
  circle(*i)  # 在變量前加一個星號就搞定啦

我們來看一下泌射,當(dāng) i 的值為(4, 3.14),那么這是一個元組鬓照,用星號能起什么作用呢熔酷?星號相當(dāng)于拆解,把元組拆解成單個的元素豺裆,再分別按順序賦值給 circle() 函數(shù)的各個參數(shù)拒秘。circle(*i) 等同于 circle(4, 3.14)。

同樣字典形式的參數(shù)收集也可以逆向來用臭猜。這個就更有用啦躺酒。比如我們連接 mysql 數(shù)據(jù)的時候(這里我只舉函數(shù)調(diào)用的例子,數(shù)據(jù)庫的使用在 Python 基礎(chǔ)學(xué)完后再深究)蔑歌,使用到的函數(shù)有很多的參數(shù):

db = connect(host=127.0.0.1, port=3306, user='root', password='123456', db='happy')  # 需要的話還有參數(shù)需要賦值

那么對于這種情況羹应,我們可以寫一個字典作為數(shù)據(jù)庫連接的配置:

db_config = {
  'host': '127.0.0.1',
  'port': 3306,
  'user': 'root',
  'password': '123456',
  'db': 'happy'
}

db = connect(**db_config)

這里兩個星號的作用,把字典拆解為單個的 參數(shù)名=參數(shù)值 的形式分別賦值給函數(shù)的各個參數(shù)次屠。

雖然代碼看起來更多一些园匹,但是可讀性更強,維護起來也更容易些劫灶,可以把這個字典放在配置文件中維護偎肃,其他需要用到的地方直接引入這個字典即可。

關(guān)鍵字參數(shù)

最后還剩一個關(guān)鍵字參數(shù)浑此,關(guān)鍵字參數(shù)在函數(shù)定義時是一種參數(shù)的限制條件累颂。

定義為關(guān)鍵字參數(shù)的參數(shù),在調(diào)用時,必須以 參數(shù)名=參數(shù)值的形式賦值紊馏,不能直接寫參數(shù)值料饥。

def person(name, age, *, sex, height):
  print('用戶的姓名為:', name)
  print('用戶的年齡為:', age)
  print('用戶的性別為:', sex)
  print('用戶的身高為:', height)

上面例子中函數(shù)參數(shù)中的星號看到了么?星號后面的參數(shù) sexheight 就是關(guān)鍵字參數(shù)了朱监。

注意星號不用賦值也不算一個參數(shù)岸啡,星號屬于一個標(biāo)識用來區(qū)分普通參數(shù)和關(guān)鍵字參數(shù)。

在函數(shù)調(diào)用時赫编,sex 和 height 兩個關(guān)鍵字參數(shù)巡蘸,必須以 sex='男' 和 height=180 這種形式賦值,否則就會報錯擂送。

>>> person('nemo', 18, '男', 180)  # 提示只需要兩個位置參數(shù)悦荒,但是給了4個
TypeError: person() takes 2 positional arguments but 4 were given

>>> person('nemo', 18)  # 提示缺少兩個關(guān)鍵字參數(shù)
TypeError: person() missing 2 required keyword-only arguments: 'sex' and 'height'

>>> person('nemo', 18, sex='男', height=180)  # 只有這樣才能正確調(diào)用
用戶的姓名為: nemo
用戶的年齡為: 18
用戶的性別為: 男
用戶的身高為: 180
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嘹吨,隨后出現(xiàn)的幾起案子搬味,更是在濱河造成了極大的恐慌,老刑警劉巖蟀拷,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碰纬,死亡現(xiàn)場離奇詭異,居然都是意外死亡问芬,警方通過查閱死者的電腦和手機悦析,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來此衅,“玉大人她按,你說我怎么就攤上這事】蝗幔” “怎么了酌泰?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長匕累。 經(jīng)常有香客問我陵刹,道長,這世上最難降的妖魔是什么欢嘿? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任衰琐,我火速辦了婚禮,結(jié)果婚禮上炼蹦,老公的妹妹穿的比我還像新娘羡宙。我一直安慰自己,他們只是感情好掐隐,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布狗热。 她就那樣靜靜地躺著钞馁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪匿刮。 梳的紋絲不亂的頭發(fā)上僧凰,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音熟丸,去河邊找鬼训措。 笑死,一個胖子當(dāng)著我的面吹牛光羞,可吹牛的內(nèi)容都是我干的绩鸣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼纱兑,長吁一口氣:“原來是場噩夢啊……” “哼呀闻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起萍启,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屏鳍,沒想到半個月后勘纯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡钓瞭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年驳遵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片山涡。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡堤结,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鸭丛,到底是詐尸還是另有隱情竞穷,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布鳞溉,位于F島的核電站瘾带,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏熟菲。R本人自食惡果不足惜看政,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抄罕。 院中可真熱鬧允蚣,春花似錦、人聲如沸呆贿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谴垫,卻和暖如春章母,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翩剪。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工乳怎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人前弯。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓蚪缀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親恕出。 傳聞我的和親對象是個殘疾皇子询枚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容