Python-六、函數(shù)的應(yīng)用

1、函數(shù)是什么

在Python中,函數(shù)不是數(shù)學(xué)函數(shù)那樣看上去冰冷無聊的規(guī)則和公式,而是有實打?qū)嵉?、有自己作用的代碼。

比如說當我們需要實現(xiàn)“打印”這個功能,會用到print();當我們需要實現(xiàn)“獲取數(shù)據(jù)長度”這個功能,會用到len()。這些都是設(shè)定好了,可以直接拿過來就用的功能,這就叫做“組織好的代碼”。

函數(shù)(Function)能實現(xiàn)的功能從簡單到復(fù)雜,各式各樣,但其本質(zhì)是相通的:“喂”給函數(shù)一些數(shù)據(jù),它就能內(nèi)部消化,給你“吐”出你想要的東西。

這就像自動販賣機,只不過販賣機是喂點錢,吐出來一些吃的喝的用的東西;而Python函數(shù)則是喂各種各樣的數(shù)據(jù),吐出來各種各樣的功能。

給函數(shù)輸入數(shù)據(jù),函數(shù)運算后輸出結(jié)果

上圖中函數(shù)后都帶個小括號,小括號里用于放你輸入的內(nèi)容,這個內(nèi)容就是“參數(shù)”,比如:

print('Hello World')

↑函數(shù)? ? ? ?↑參數(shù)

函數(shù)的定義:函數(shù)是組織好的、可以重復(fù)使用的、用來實現(xiàn)單一功能的代碼。

用販賣機來打比方,販賣機是設(shè)定好可以直接使用(組織好的),可以重復(fù)上架售賣不同的物品(重復(fù)使用),功能是賣東西(單一功能)。

而函數(shù)呢?以print()函數(shù)為例,它也是設(shè)定好可以直接使用(組織好的),不論你想打印什么參數(shù)都可以(重復(fù)使用),而print函數(shù)能實現(xiàn)的單一功能就是“打印”。

那么問題來了,販賣機不一定有我們享要的東西,同理PYTHON自帶的內(nèi)置函數(shù)有限,那我們怎么通過編程,自定獨一無二的函數(shù)呢?

2、定義和調(diào)用函數(shù)

2.1、定義函數(shù)

我們可以通過函數(shù)的語法來定義一個函數(shù)。

定義函數(shù)的語法

比如:

def greet(name):? ? ? ? ? ? ? ? ? #def的意思是定義(define),greet是【函數(shù)名】,name是參數(shù)

? ? print(name+'早上好')? ? ????#函數(shù)(函數(shù)體)要實現(xiàn)的功能:打印出“name+早上好”這句話。

? ? return? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#函數(shù)內(nèi)部一旦遇到return語句,就會停止執(zhí)行并返回結(jié)果。

PS:沒有return語句的函數(shù),Python也會在末尾隱性地加上return None,即返回None值(return None可以簡寫為return)。所以我們經(jīng)常可以省略這個return。

上面這段代碼執(zhí)行后,什么都沒有,一片空白……那是因為我們只定義了函數(shù),還沒有調(diào)用它!

2.1、調(diào)用函數(shù)

函數(shù)咋調(diào)用?喊函數(shù)的名字就可以了!如下

def pika1():

? ? print('我最喜愛的神奇寶貝是皮卡丘')

#該函數(shù)沒有參數(shù),直接調(diào)用函數(shù)名。記得英文括號一定不能少

pika1()????#←←←←←這里就開始喊函數(shù)pika1的名字了

def pika2(name):

? ? print('我最喜愛的神奇寶貝是'+name)

#需要給參數(shù)name賦值,每次調(diào)用都可以給參數(shù)賦不同的值

pika2('皮卡丘')

pika2('噴火龍')

def pika3(name,person):

? ? print('我最喜愛的神奇寶貝是'+name)

? ? print('我最喜愛的馴獸師是'+person)

#需要給兩個參數(shù)分別賦值,并用逗號隔開,否則會報錯

pika3('卡比獸','小智')

函數(shù)的調(diào)用結(jié)果如下:

我最喜愛的神奇寶貝是皮卡丘

我最喜愛的神奇寶貝是皮卡丘

我最喜愛的神奇寶貝是噴火龍

我最喜愛的神奇寶貝是卡比獸

我最喜愛的馴獸師是小智

函數(shù)的調(diào)用關(guān)鍵是:弄清楚這個函數(shù)有多少個參數(shù),如何給參數(shù)賦值,這個過程在函數(shù)里叫做參數(shù)的傳遞(pass)。

函數(shù)能將復(fù)雜的語句和功能統(tǒng)一封裝進一個函數(shù)名里,調(diào)用者只需明白函數(shù)能實現(xiàn)什么,根據(jù)需要傳遞參數(shù)即可。

擴展,tree()函數(shù)打印圣誕樹:

def tree(Height):

? ? print('Merry Christmas!')

? ? for i in range(Height):

? ? ? ? print((Height-i)*2*' '+'o'+ i*'~x~o')

? ? ? ? print(((Height-i)*2-1)*' '+(i*2+1)*'/'+'|'+(i*2+1)*'\\')

tree(6) #通過對tree函數(shù)輸入height參數(shù),即可生成圣誕樹,我們以6層為例

輸出結(jié)果:


6層圣誕樹

3、函數(shù)重要概念

3.1、參數(shù)類型

主要的參數(shù)類型有:位置參數(shù)、默認參數(shù)、不定長參數(shù)。我們用一個案例把這些參數(shù)串起來。

假設(shè)有一家深夜食堂,顧客可以任意點菜。但因為人手不足,所以只能為每個人提供一份開胃菜和一份主食。如果寫成函數(shù)的形式,這個函數(shù)就會有兩個參數(shù)。

(開胃菜和主食的英文分別是appetizer和course)

def menu(appetizer,course):

? ? print('一份開胃菜:'+appetizer)

? ? print('一份主食:'+course+'\n')

#還記得轉(zhuǎn)義字符\n吧,表示換行

menu('牛肉拉面','話梅花生')

menu('話梅花生','牛肉拉面')

#如果采用下面這種形式傳遞,就不需要理會參數(shù)位置。

menu(course='牛肉拉面',appetizer='話梅花生')

運行結(jié)果:

第三個因為用的=賦值,所以按照函數(shù)的默認位置做輸出

回到這個食堂的故事。經(jīng)營了一陣子之后,為了吸引更多的人流,你決定給每個顧客免費送上一份甜品綠豆沙,這時候你就可以用到【默認參數(shù)】,注意:默認參數(shù)必須放在位置參數(shù)之后。

def menu(appetizer,course,dessert): #在函數(shù)里增加一個甜品就好啦

后來呢,盛夏來襲,你覺得賣燒烤是個不錯的主意。但問題是每個人點的烤串數(shù)量都不同,你也不能限定死數(shù)量,這時候【不定長參數(shù)】就能派上用場,即不確定傳遞參數(shù)的數(shù)量。他的格式是一個星號*加上參數(shù)名。

def menu(*barbeque):

? ? print(barbeque)

menu('烤雞翅','烤茄子','烤玉米')

#這幾個值都會傳遞給參數(shù)barbeque


運行結(jié)果出來啦

看,輸出結(jié)果是('烤雞翅', '烤茄子', '烤玉米'),這種數(shù)據(jù)類型就跟元組(tuple)一樣哦。

看,雖然我們只定義了一個參數(shù),但是可以隨便往參數(shù)里加?xùn)|西哦!

現(xiàn)在,讓我們開始點餐吧,用for循環(huán)向不定長參數(shù)里輸入值(燒烤),并把前菜、主菜、甜點一起拼湊為一張菜單吧:

def menu(appetizer,course,*barbeque,dessert='熔巖巧克力'):

? ? print('開胃菜 '+appetizer)

? ? print('主菜 '+course)

? ? print('甜品 '+dessert)

? ? for i in barbeque:? #注意FOR循環(huán)與不定長參數(shù)

? ? ? ? print('燒烤 '+i)? #的用法,i就是這個不定長參數(shù)哦

menu('小紅莓','生烤牛肉','熔巖巧克力++','烤雞翅','烤豬勁肉','烤玉米')

輸出結(jié)果

3.2、return的作用

return是返回值,當你輸入?yún)?shù)給函數(shù),函數(shù)就會返回一個值給你。

而print()函數(shù)本身比較特殊,它在屏幕上顯示完相關(guān)的文本內(nèi)容就沒了,并不會返回一個值給我們。所以,它返回的是空值(None)。

在自定義函數(shù)的時候,我們就可以用return語句規(guī)定該函數(shù)要返回什么值給我們。帶return語句的函數(shù)是這樣的:

def niduoda(age):

? ? if age < 12:

? ? ? ? return '哈,是祖國的花朵啊'

? ? elif age < 25:

? ? ? ? return '哇,是小鮮肉呢'

? ? else:

? ? ? ? return '嗯,人生才剛剛開始'

print(niduoda(30))

在上例中,函數(shù)是互相嵌套的,niduoda()函數(shù)就被嵌套在print()函數(shù)里。那為什么在這個例子中,不直接用print,為啥還要用return呢?

因為我們在上面的立體中,要求把函數(shù)功能執(zhí)行后,第一時間把參數(shù)打印出來。而在很多時候,當多個函數(shù)之間相互配合時,我們并不需要第一時間就將結(jié)果打印出來,而是需要將某個返回值先放著,等到需要的時候再做進一步的處理。

return語句-總結(jié)1:如果不是立即要對函數(shù)返回值做操作,那么可以使用return語句保留返回值。

來,讓我們做個案例試試看。

在我們關(guān)于愛情的天真幻想中,我希望我的夢中情人擁有XXX的臉蛋和XXX的身材。

這個需求,需要我們做兩點:一、分別定義兩個函數(shù),參數(shù)為人名,能夠返回字符串'XXX的臉蛋'和'XXX的身材';二、將上述兩個函數(shù)的返回值拼接在一起之后,再打印出來。請你先思考一下,再點擊回車。

def face(name):

? ? return name + '的臉蛋'

def body(name):

? ? return name + '的身材'

print('我的夢中情人:'+face('李若彤') +' + ' + body('林志玲'))

print('我的夢中情人:'+face('新垣結(jié)衣) +' + ' + body(''長澤雅美))? ?#如要再打印,得再輸入調(diào)用

所以更常見的做法是:再定義一個主函數(shù)main(),參數(shù)調(diào)用前兩個函數(shù)的返回值。老師先給出代碼,你可以琢磨一下,主要思考第5行和第6行代碼。

def face(name):

? ? return name + '的臉蛋'

def body(name):

? ? return name + '的身材'

def main(dream_face,dream_body):

? ? return '我的夢中情人:' + face(dream_face) + ' + ' + body(dream_body)

#使用main函數(shù)以后,就只調(diào)用一次了~

print(main('李若彤','林志玲'))

print(main('新垣結(jié)衣','長澤雅美'))

這個代碼有點繞,讓我們做個圖解:


函數(shù)與main函數(shù)

return語句-總結(jié)2:需要多次調(diào)用函數(shù)時,可以再定義一個主函數(shù)main(),調(diào)用非主函數(shù)的返回值。

現(xiàn)在,我們嘗試用另外的方法來一次性返回這兩個值:

def lover(name1,name2):

? ? face = name1 + '的臉蛋'

? ? body = name2 + '的身材'

? ? return face,body

a=lover('李若彤','林志玲')

print('我的夢中情人:'+a[0]+' + '+a[1])

一次性返回的兩個值,是('李若彤的臉蛋', '林志玲的身材')這樣一個元組。

Python語言中的函數(shù)返回值可以是多個,而其他語言都不行,這是Python相比其他語言的簡便和靈活之處。一次接受多個返回值的數(shù)據(jù)類型就是元組。

return語句-總結(jié)3:python的函數(shù)返回值可以是多個,多個返回值的數(shù)據(jù)類型是元組(tuple)。

return語句-總結(jié)4:沒有return語句的函數(shù)會默認返回None值。

示例:

def fun():

? ? a ='I am coding'

print(fun())

運行結(jié)果:None

return語句-總結(jié)5:一旦函數(shù)內(nèi)部遇到return語句,就會停止執(zhí)行并返回結(jié)果。

示例:

def fun():

? return 'I am coding.'

? return 'I am not coding.'

print(fun())

運行結(jié)果:I am coding.

3.3 鞏固練習(xí)

習(xí)題:

一、定義一個帶有兩個參數(shù)的函數(shù),函數(shù)的功能是返回兩個參數(shù)中較大的那個值;二、調(diào)用函數(shù),將99的平方和8888賦值給參數(shù),并將較大值打印出來。

思路:

1、定義存儲兩個參數(shù)的函數(shù),函數(shù)將比較這兩個參數(shù);

2、返回較大的值。

代碼:

def bigdata(num1,num2):

? ? if num1 > num2:

? ? ? ? return num1

? ? else:

? ? ? ? return num2

print(bigdata(99**2,8888))

3.4、變量作用域

當我們定義一個函數(shù)的時候,很重要的事情就是理解函數(shù)中變量的作用域。

第一點:在一個函數(shù)內(nèi)定義的變量僅能在函數(shù)內(nèi)部使用(局部作用域),它們被稱作【局部變量】。

第二點:在所有函數(shù)之外賦值的變量,可以在程序的任何位置使用(全局作用域),它們叫【全局變量】。

例:

x=99 #全局變量x

def num():

? ? x=88 #局部變量x

? ? print(x)

num()

#打印局部變量x

print(x)

#打印全局變量x

因為x=99是在函數(shù)外賦值的,所以第一個變量x是全局變量;x=88是在函數(shù)內(nèi)賦值的,所以第二個變量x是局部變量。

局部和全局變量

我們可以將定義的函數(shù)想象成一個私人房間,所以里面存數(shù)據(jù)的容器(變量)是私有的,只能在個人的房間里使用;而在函數(shù)外存數(shù)據(jù)的變量是公用的,沒有使用限制。

局部作用域和全局作用域

我們來看看容易新手容易踩的坑:

def egg():?

? ? quantity = 108

egg()

print(quantity)?

運行結(jié)果:NameError: name 'quantity' is not defined,這句話翻譯成中文就是:變量quantity并沒有被定義。其實,我們定義了,只不過是在函數(shù)egg() 內(nèi)定義的,所以這是個局部變量。但問題是我們不能在定義的函數(shù)egg() 外面,也就是不能在全局作用域中使用這個局部變量。

怎么辦呢?其實也很簡單,就像私人房間里的人可以使自由使用公共區(qū)域的物品,在函數(shù)內(nèi)部的局部作用域,是可以訪問全局變量的。

quantity = 108? ? ?#定義變量quantity,這不是在我們定義的函數(shù)內(nèi)的,所以是全局變量。

def egg():

? print(quantity)? ??#函數(shù)內(nèi)的功能是打印變量quantity

egg()? ? ? ? ? ? ? ? ? ?#調(diào)用這個函數(shù)

記住一句話,當變量處于被定義的函數(shù)內(nèi)時,就是局部變量,只能在這個函數(shù)內(nèi)被訪問;當變量處于被定義的函數(shù)外時,就是全局變量,可以在程序中的任何位置被訪問。

如果你非要將局部變量變成全局變量,就像把私人房間的東西挪到公共區(qū)域,可不可以呢?Python也是能夠滿足你的,只不過要用到一種新的語句global語句,就像這樣子:

def egg():

? ? global quantity? ? ? #global語句將變量quantity聲明為全局變量

? ? quantity = 108

egg()

print(quantity)

3.5、練習(xí) 1-Hello Kitty抽獎

練習(xí)目標:

我們會通過今天的項目練習(xí),學(xué)習(xí)函數(shù)的封裝和調(diào)用。?

練習(xí)要求:

我們已經(jīng)有一個hellokitty抽獎器,現(xiàn)在,請你把這個程序封裝成一個新的函數(shù)。

運行抽獎器的代碼:

# 查看注釋,運行代碼。

import random

import time

# 用random函數(shù)在列表中隨機抽獎,列表中只有3位候選者。

luckylist = ['海綿寶寶','派大星','章魚哥']

# random模塊中有個隨機選取一個元素的方法:random.choice()。

a = random.choice(luckylist)? # 從3個人中隨機選取1個人。

print('開獎倒計時',3)

time.sleep(1)? # 調(diào)用time模塊,控制打印內(nèi)容出現(xiàn)的時間

print('開獎倒計時',2)

time.sleep(1)

print('開獎倒計時',1)

time.sleep(1)

# 使用三引號打印hellokitty的頭像

image = '''

/\_)o<

|? ? ? \\

| O . O|

\_____/

'''

print(image)? # ……

print('恭喜'+a+'中獎!')? # 使用print函數(shù)打印幸運者名單

#我了個去,這排版變這樣子,HelloKitty都扭曲了,太難看了,要在程序里跑才能正常。

思路:

這段代碼中,時間調(diào)用模塊是可以用通過for循環(huán)調(diào)用函數(shù)實現(xiàn)的,來試試看吧。

# 查看注釋,運行代碼。

import random

import time

# 用random函數(shù)在列表中隨機抽獎,列表中只有3位候選者。

def main(a,b,c):

? ? luckylist = [a,b,c]

? ? a = random.choice(luckylist) # 從3個人中隨機選取1個人。

# random模塊中有個隨機選取一個元素的方法:random.choice()。

? ? x = 4

? ? for i in range(1,x):

? ? ? ? y = x - i

? ? ? ? print('開獎倒計時',y)

? ? ? ? time.sleep(1) # 調(diào)用time模塊,控制打印內(nèi)容出現(xiàn)的時間

# 使用三引號打印hellokitty的頭像

? ? image = '''

? ? /\_)o<

? ? |? ? ? \\

? ? | O . O|

? ? \_____/

? ? '''

? ? print(image)

? ? print('恭喜'+a+'中獎!')? # 使用print函數(shù)打印幸運者名單

main('張三','李四','王五')

抽獎函數(shù)封裝練習(xí)

3.6、練習(xí)2-打印52張撲克牌

練習(xí)目標

通過這個練習(xí),你可以通過Python優(yōu)雅地生成一副撲克牌。?

練習(xí)要求

我們將通過這個練習(xí),簡單地復(fù)習(xí)一下return的用法。另外,這個練習(xí)也要求你能夠快速地學(xué)習(xí)新知識并將其運用出來。新知識有3個:一種新的列表生成方式、extend 的新用法和列表生成式。

# 知識1:一種新的列表生成方式

num1 = [1,2,3,4,5]? # 想一想,如果用這個方法生成一個1-100的列表……

num2 = list(range(1,6))

print(num1)

print(num2)

# 知識2:extend 的新用法

num2.extend(['ABCDE'])

num2.extend('ABCDE')? # extend后面是列表的話會將其合并,后面是字符串的話會將每個字符當成一個列表中的元素。

print(num2)

# 知識點3:列表生成式

list1 = [i for i in range(3)]? # 規(guī)定列表中元素的范圍

print(list1)

list2 = [m+n for m in ['天字', '地字'] for n in '一二']? # 列表元素可以是組合,分別規(guī)定范圍。

print(list2)

list3 = [n*n for n in range(1,11) if n % 3 == 0]? # 元素既可規(guī)定范圍,也可附加條件。

print(list3)

通過新知識點,補全函數(shù)cards()。

#每張撲克牌的展現(xiàn)形式是一個元組:(花色,大?。?/p>

# 函數(shù)會返回一個撲克牌列表,里面有52個元組(將花色和數(shù)字分開),對應(yīng)52張牌。(代碼量5行左右)

思路:

1、撲克牌有52張,10以上是JOKA,就是每組13張。則需要預(yù)置元組1存儲花色:黑紅梅方;通過數(shù)字取值范圍+預(yù)置分別定義并組合為元組2存儲牌的大小:2<10<JQKA。

2、循環(huán)遍歷元組1與元組2,將數(shù)據(jù)返還給調(diào)用者,調(diào)用者將返還的數(shù)據(jù)打印出來。

def cards():

? ? # 在下方補充4行代碼(左右),讓函數(shù)下方的打印函數(shù)打印出52張撲克牌。每張撲克牌的展現(xiàn)形式是元組(花色,大小)。

? ? cards_suit =['黑桃','紅桃','梅花','方塊']????????#存儲好花色

? ? cards_range = list(range(2,11))? ? ? ? ? ? ? ? ?#存儲好2~10的牌號

? ? cards_range.extend('JQKA')? ? ? ? ? ? ? ? ? ? ?#把JQKA加入牌號里

? ? return [m+n for m in cards_suit for n in list(map(str,cards_range))]? ??

? ??#把牌號組合好返還,但cards_range中有一部分是數(shù)字,所以組合前要轉(zhuǎn)為str

print(cards())? # 將函數(shù)的返回值打印出來

打印52張撲克牌
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容