Python函数之初体验
定義函數(shù)
在Python中,定義一個(gè)函數(shù)要使用def語(yǔ)句,依次寫(xiě)出函數(shù)名、括號(hào)、括號(hào)中的參數(shù)和冒號(hào):,然后,在縮進(jìn)塊中編寫(xiě)函數(shù)體,函數(shù)的返回值用return語(yǔ)句返回。
我們先定義一個(gè)求字符串長(zhǎng)度的函數(shù)(無(wú)參數(shù)、無(wú)return)為例:
1 #函數(shù)定義 2 def mylen(): 3 """計(jì)算s1的長(zhǎng)度""" 4 s1 = "hello world" 5 length = 0 6 for i in s1: 7 length = length+1 8 print(length) 9 10 #函數(shù)調(diào)用 11 mylen()注釋:每一個(gè)函數(shù)都應(yīng)該對(duì)功能和參數(shù)進(jìn)行相應(yīng)的說(shuō)明,應(yīng)該寫(xiě)在函數(shù)下面第一行。以增強(qiáng)代碼的可讀性。
調(diào)用:就是?函數(shù)名()?要記得加上括號(hào),好么好么好么。
?
函數(shù)的返回值:
一般在函數(shù)中都添加一行:return ***
1 #函數(shù)定義 2 def mylen(): 3 """計(jì)算s1的長(zhǎng)度""" 4 s1 = "hello world" 5 length = 0 6 for i in s1: 7 length = length+1 8 return length 9 10 #函數(shù)調(diào)用 11 str_len = mylen() 12 print('str_len : %s'%str_len)簡(jiǎn)單做一個(gè)形容:函數(shù)好比一個(gè)加工廠,參數(shù)(非必要)好比是原材料,return的值好比加工出來(lái)的產(chǎn)品。
共有三種情況:無(wú)產(chǎn)品輸出、一個(gè)產(chǎn)品、多個(gè)產(chǎn)品
1、沒(méi)有返回值:無(wú)return、return、return None
? ? 這三種情況都相當(dāng)于return None即無(wú)返回值
? ? 常規(guī)寫(xiě)法:函數(shù)末尾 直接return?
? ? 注意:return的其他用法,就是一旦遇到return,結(jié)束整個(gè)函數(shù)。但并不是一個(gè)函數(shù)只能有一個(gè)return這個(gè)語(yǔ)句。如下:
1 def test_return(x): 2 if x > 0: 3 return x 4 else: 5 return 0 1 def ret_demo(): 2 print(111) 3 return 4 print(222) 5 6 ret = ret_demo() 7 print(ret)# 試一下,看看最后print什么?是111 222都打印了么?
2、返回一個(gè)值?
只需在return后面寫(xiě)上要返回的內(nèi)容即可。
1 #函數(shù)定義 2 def mylen(): 3 """計(jì)算s1的長(zhǎng)度""" 4 s1 = "hello world" 5 length = 0 6 for i in s1: 7 length = length+1 8 return length 9 10 #函數(shù)調(diào)用 11 str_len = mylen() 12 print('str_len : %s'%str_len)注意:return和返回值之間要有空格,可以返回任意數(shù)據(jù)類型的值
3、返回多個(gè)值
1 def ret_demo1(): 2 '''返回多個(gè)值''' 3 return 1,2,3,4 4 5 6 def ret_demo2(): 7 '''返回多個(gè)任意類型的值''' 8 return 1,['a','b'],3,4 9 10 ret1 = ret_demo1() 11 print(ret1) 12 ret2 = ret_demo2() 13 print(ret2)返回的多個(gè)值會(huì)被組織成元組被返回,也可以用多個(gè)值來(lái)接收
def ret_demo2():return 1,['a','b'],3,4#返回多個(gè)值,用一個(gè)變量接收 ret2 = ret_demo2() print(ret2)#返回多個(gè)值,用多個(gè)變量接收 a,b,c,d = ret_demo2() print(a,b,c,d)#用多個(gè)值接收返回值:返回幾個(gè)值,就用幾個(gè)變量接收 a,b,c,d = ret_demo2() print(a,b,c,d)函數(shù)的參數(shù)
先來(lái)一段代碼體驗(yàn)一下:
#函數(shù)定義 def mylen(s1):"""計(jì)算s1的長(zhǎng)度"""length = 0for i in s1:length = length+1return length#函數(shù)調(diào)用 str_len = mylen("hello world") print('str_len : %s'%str_len)我們告訴mylen函數(shù)要計(jì)算的字符串是誰(shuí),這個(gè)過(guò)程就叫做?傳遞參數(shù),簡(jiǎn)稱傳參,我們調(diào)用函數(shù)時(shí)傳遞的這個(gè)“hello world”和定義函數(shù)時(shí)的s1就是參數(shù)。
上面講過(guò)參數(shù)好比一個(gè)原材料,函數(shù)屬于加工廠。在加工之前需要將原材料傳遞到工廠,這個(gè)過(guò)程就相當(dāng)于傳參的過(guò)程。
參數(shù)有兩種:形參、實(shí)參
我們調(diào)用函數(shù)時(shí)傳遞的這個(gè)“hello world”被稱為實(shí)際參數(shù),因?yàn)檫@個(gè)是實(shí)際的要交給函數(shù)的內(nèi)容,簡(jiǎn)稱實(shí)參。
定義函數(shù)時(shí)的s1,只是一個(gè)變量的名字,被稱為形式參數(shù),因?yàn)樵诙x函數(shù)的時(shí)候它只是一個(gè)形式,表示這里有一個(gè)參數(shù),簡(jiǎn)稱形參。
站在實(shí)參角度:
1、按照位置傳參
def mymax(x,y):#此時(shí)x=10,y=20the_max = x if x > y else yreturn the_maxma = mymax(10,20) print(ma)2.按照關(guān)鍵字傳值
def mymax(x,y):#此時(shí)x = 20,y = 10print(x,y)the_max = x if x > y else yreturn the_maxma = mymax(y = 10,x = 20) print(ma)3.位置、關(guān)鍵字形式混著用
def mymax(x,y):#此時(shí)x = 10,y = 20print(x,y)the_max = x if x > y else yreturn the_maxma = mymax(10,y = 20) print(ma)
正確用法
問(wèn)題一:位置參數(shù)必須在關(guān)鍵字參數(shù)的前面
問(wèn)題二:對(duì)于一個(gè)形參只能賦值一次
?
站在形參角度
位置參數(shù)
如果定義函數(shù)時(shí)填寫(xiě)了位置參數(shù),調(diào)用該函數(shù)時(shí)必須輸入相應(yīng)的參數(shù)
1 def mymax(x,y): 2 #此時(shí)x = 10,y = 20 3 print(x,y) 4 the_max = x if x > y else y 5 return the_max 6 7 #調(diào)用mymax不傳遞參數(shù) 8 ma = mymax() 9 print(ma) 10 11 #結(jié)果 12 TypeError: mymax() missing 2 required positional arguments: 'x' and 'y'默認(rèn)參數(shù)
為什么要有默認(rèn)參數(shù):將變化比較小的值設(shè)置成默認(rèn)參數(shù),降低調(diào)用函數(shù)的難度。
1.默認(rèn)參數(shù)的定義
def stu_info(name,sex = "male"):"""打印學(xué)生信息函數(shù),由于班中大部分學(xué)生都是男生,所以設(shè)置默認(rèn)參數(shù)sex的默認(rèn)值為'male'"""print(name,sex)stu_info('alex') stu_info('eva','female')2.參數(shù)陷阱:默認(rèn)參數(shù)是一個(gè)可變數(shù)據(jù)類型
默認(rèn)參數(shù)很有用,但使用不當(dāng),也會(huì)掉坑里。默認(rèn)參數(shù)有個(gè)最大的坑,演示如下:
先定義一個(gè)函數(shù),傳入一個(gè)list,添加一個(gè)END再返回:
def add_end(L=[]):L.append('END')return L當(dāng)你正常調(diào)用時(shí),結(jié)果似乎不錯(cuò):
>>> add_end([1, 2, 3]) [1, 2, 3, 'END'] >>> add_end(['x', 'y', 'z']) ['x', 'y', 'z', 'END']當(dāng)你使用默認(rèn)參數(shù)調(diào)用時(shí),一開(kāi)始結(jié)果也是對(duì)的:
>>> add_end() ['END']但是,再次調(diào)用add_end()時(shí),結(jié)果就不對(duì)了:
>>> add_end() ['END', 'END'] >>> add_end() ['END', 'END', 'END']很多初學(xué)者很疑惑,默認(rèn)參數(shù)是[],但是函數(shù)似乎每次都“記住了”上次添加了'END'后的list。
原因解釋如下:
Python函數(shù)在定義的時(shí)候,默認(rèn)參數(shù)L的值就被計(jì)算出來(lái)了,即[],因?yàn)槟J(rèn)參數(shù)L也是一個(gè)變量,它指向?qū)ο骩],每次調(diào)用該函數(shù),如果改變了L的內(nèi)容,則下次調(diào)用時(shí),默認(rèn)參數(shù)
的內(nèi)容就變了,不再是函數(shù)定義時(shí)的[]了。
所以,定義默認(rèn)參數(shù)要牢記一點(diǎn):默認(rèn)參數(shù)必須指向不變對(duì)象!
? 要修改上面的例子,我們可以用None這個(gè)不變對(duì)象來(lái)實(shí)現(xiàn):
def add_end(L=None):if L is None:L = []L.append('END')return L現(xiàn)在,無(wú)論調(diào)用多少次,都不會(huì)有問(wèn)題:
>>> add_end() ['END'] >>> add_end() ['END']為什么要設(shè)計(jì)str、None這樣的不變對(duì)象呢?因?yàn)椴蛔儗?duì)象一旦創(chuàng)建,對(duì)象內(nèi)部的數(shù)據(jù)就不能修改,這樣就減少了由于修改數(shù)據(jù)導(dǎo)致的錯(cuò)誤。此外,由于對(duì)象不變,多任務(wù)環(huán)境下
同時(shí)讀取對(duì)象不需要加鎖,同時(shí)讀一點(diǎn)問(wèn)題都沒(méi)有。我們?cè)诰帉?xiě)程序時(shí),如果可以設(shè)計(jì)一個(gè)不變對(duì)象,那就盡量設(shè)計(jì)成不變對(duì)象。
動(dòng)態(tài)參數(shù)
按位置傳值多余的參數(shù)都由args統(tǒng)一接收,保存成一個(gè)元組的形式?
def mysum(*args):the_sum = 0for i in args:the_sum+=ireturn the_sumthe_sum = mysum(1,2,3,4) print(the_sum) def stu_info(**kwargs):print(kwargs)print(kwargs['name'],kwargs['sex'])stu_info(name = 'alex',sex = 'male') 1、2、3、4從左到右定義# def f(a,b,*args,defult=6,**kwargs): # #位置參數(shù),*args,默認(rèn)參數(shù),**kwargs # print(a,b,args,defult)總結(jié):
Python的函數(shù)具有非常靈活的參數(shù)形態(tài),既可以實(shí)現(xiàn)簡(jiǎn)單的調(diào)用,又可以傳入非常復(fù)雜的參數(shù)。
默認(rèn)參數(shù)一定要用不可變對(duì)象,如果是可變對(duì)象,程序運(yùn)行時(shí)會(huì)有邏輯錯(cuò)誤!
要注意定義可變參數(shù)和關(guān)鍵字參數(shù)的語(yǔ)法:
*args是可變參數(shù),args接收的是一個(gè)tuple;
**kwargs是關(guān)鍵字參數(shù),kwargs接收的是一個(gè)dict。
以及調(diào)用函數(shù)時(shí)如何傳入可變參數(shù)和關(guān)鍵字參數(shù)的語(yǔ)法:
可變參數(shù)既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過(guò)*args傳入:func(*(1, 2, 3));
關(guān)鍵字參數(shù)既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過(guò)**kwargs傳入:func(**{'a': 1, 'b': 2})。
使用*args和**kwargs是Python的習(xí)慣寫(xiě)法,當(dāng)然也可以用其他參數(shù)名,但最好使用習(xí)慣用法。
命名的關(guān)鍵字參數(shù)是為了限制調(diào)用者可以傳入的參數(shù)名,同時(shí)可以提供默認(rèn)值。
定義命名的關(guān)鍵字參數(shù)在沒(méi)有可變參數(shù)的情況下不要忘了寫(xiě)分隔符*,否則定義的將是位置參數(shù)。
轉(zhuǎn)載于:https://www.cnblogs.com/buyisan/p/7252398.html
總結(jié)
以上是生活随笔為你收集整理的Python函数之初体验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spark2.x 与 Spark1.x
- 下一篇: Python__封装