天天看點

Day8.函數那些事兒

例題引導:

【模拟輪盤抽獎遊戲】

輪盤分為三部分: 一等獎, 二等獎和三等獎;輪盤轉的時候是随機的,獎項設定如下:如果範圍在[0,0.08)之間,代表一等獎,如果範圍在[0.08,0.3)之間,代表2等獎,如果範圍在[0, 1.0)之間,代表3等獎,

要求:假設本次活動1000人參加, 模拟遊戲時各等級獎品個數需要準備多少個。

解題思路:定義遊戲規則(用字典表達)-建構函數-生成随機數-編寫遊戲邏輯-調用函數-周遊1000名使用者-列印輸出

參考答案:

import random  #導入随機數子產品

rewardDict = {
    '一等獎': (0, 0.08),
    '二等獎': (0.08, 0.3),
    '三等獎': (0.3, 1)
}      #因為該值為一對一映射,是以想到用字典定義得獎範圍

def rewardFun():    #開始建構函數
    """使用者得獎等級"""
    # 生成一個0~1之間的随機數
    num = random.random()
    # 判斷随機轉盤轉的數是幾等獎
    for k, v in rewardDict.items():  
        # 這裡的v是元組
        if v[0] <= num < v[1]:
            return k

# print rewardFun()
resultDict = {}

for i in range(1000):
    # res:本次轉盤的等級(一/二/三等獎)
    res = rewardFun()  #調用函數
    if res not in resultDict:
        resultDict[res] = 1
    else:
        resultDict[res] = resultDict[res] + 1

for k, v in resultDict.items():
    print k, '---------->', v           

複制

學習引導:

  • 函數概念
  • 函數定義
  • 函數調用
  • 參數調用
  • 參數傳遞

函數的概念

函數是将具有獨立功能的代碼塊組織成為一個整體,使其具有特殊功能的代碼集。它是編輯好的、可直接調用的、可重複使用的,用來實作單一或相關聯功能的代碼段

優點:

  • 提高程式的子產品性;
  • 使程式變得可擴充;
  • 減少重複代碼;
  • 使程式變得可維護;

函數的定義

函數必須先建立才可以使用,該過程稱為函數定義,使用函數的過程稱為函數調用。

函數可以根據自己的需求來定義,但有一些規則需要注意:

  • 函數代碼塊必須以def開頭,後接函數辨別符名稱和圓括号();
  • 任何傳入參數和自變量必須放在圓括号中間,圓括号之間可以用于定義參數;
  • 函數的第一行語句可以選擇性的使用文檔字元-用于存放函數說明;
  • 函數内容以冒号起始,并且縮進;
  • 函數名稱的命名應符合辨別符的命名規則;(可由字母、下劃線和數字組成;不能以數字開頭;不能與關鍵字重名)
  • return[表達式]結束函數,選擇性地傳回一個值給調用方。不帶表達式的return相當于傳回None

函數定義的一般格式:

#函數定義的一般格式:
def 函數名 (參數清單):
    函數體           

複制

#執行個體1
def hello():
    print('Hello World')
    
hello()           

複制

#Hello World           

複制

執行個體2-計算圓的面積,帶參數

#執行個體2-計算圓的面積,帶參數
def area(r):
    pi=3.412
    return pi*(r^2)

r=5
print('圓的面積為:',area(r))           

複制

#圓的面積為: 23.884           

複制

函數調用

即使用函數的過程

簡單的調用應用

#函數功能:列印該字元串
def println(str):
    print(str)
    return

#調用函數
println('調用上述函數')
println('列印這段字元串')
println('多次調用函數')           

複制

#調用上述函數
#列印這段字元串
#多次調用函數           

複制

參數調用

參數分為形參、實參

  • 形參:函數定義時括号内的參數
  • 實參:函數調用時括号内的參數
  • 形參相當于變量,實參相當于變量的值

在實際代碼中表示如下:

#定義時:
def func(a,b,c):
    pass

其中 a,b,c 為形參

#調用時:
func(1,2,3)
其中1,2,3為實參           

複制

形參:

隻在被調用時,才配置設定存儲單元。調用結束,立刻釋放所配置設定的記憶體。

形參隻在函數内部有效

實參:

可以是:常量、變量、表達式、函數

進行函數調用時,實參必須是确定的值

位置參數:

  • 位置形參:函數定義時,從左往右寫的參數,比如上面的 a, b , c
  • 位置實參:函數調用時,從左往右寫的參數, 比如上面的 1,2,3
  • 位置形參定義多少個,調用時位置實參必須寫上多少個,多一個少一個都不行。
  • 位置參數必須以正确的順序傳入函數。調用時的數量必須和聲明時的一樣。
def func(a,b,c):
    return a+b+c

#調用
print(func(2,3,4))             

複制

#9           

複制

錯誤示範:

def func(a,b,c):
    return a+b+c

#調用
print(func(2,3)) #實參數量不對應,報錯           

複制

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-21-38b482e25fef> in <module>
      3 
      4 #調用
----> 5 print(func(2,3))
TypeError: func() missing 1 required positional argument: 'c'           

複制

關鍵參數:

  • 正常情況下,給函數傳參數,要按順序。如果不想按順序,就用關鍵參數。
  • 指定參數名的參數,就叫做關鍵參數。
  • 函數調用時:func(a=1, b=2), 這種指定了參數名的參數,就是關鍵參數。
  • 調用函數時,關鍵參數可以和位置參數一起用,但是關鍵參數必須在位置參數的後面。不然會報錯。
def func(a,b,c):
    return a+b+c

#調用
print(func(4,c=3,b=2))             

複制

#9           

複制

預設參數:

  • 函數定義時,預設參數必須在位置形參的後面。
  • 函數調用時,指定參數名的參數,叫關鍵參數。
  • 而在函數定義時,給參數名指定值的時候,這個參數叫做預設參數。
  • 關鍵參數,和預設參數兩個參數寫法一樣,差別在于:

    關鍵參數是在函數調用時,指定實參的參數名,也可以說指定值的參數名。

    預設參數是在函數定義時,指定參數名的值。

  • 寫法:

    def (a, b=100): pass

  • 定義時,有預設參數的話,調用時,這個實參可以不寫。如果實參不寫的話,這個形參的參數值是他的預設值。

執行個體示範:

def info(name,age=18):
    print('名字:',name)
    print('年齡:',age)
    return 

#調用
info(age=22,name='Jack')
print('****************')
info(name='Jack')           

複制

'''
名字: Jack
年齡: 22
*****************
名字: Jack
年齡: 18
'''           

複制

動态參數:* args ** kwargs

當你需要一個函數能處理很多參數,超過已聲明的參數數量,這時就需要動态參數。與上述兩中參數不同的是,該參數聲明不需要命名。

* args

一個'* '的參數會以元組(tuple)的形式導入,存放未命名的變量參數

#函數定義
def printinfo(arg1,*vartuple):
    print('輸出:')
    print(arg1)
    print(vartuple)
    
#調用
printinfo(34,45,32,12)           

複制

#輸出:
#34
#(45, 32, 12)           

複制

如果函數調用時沒有指定參數,動态參數則表現為空元組。

#函數定義
def printinfo(arg1,*vartuple):
    print('輸出:')
    print(arg1)
    print(vartuple)
    
#調用
printinfo(34)           

複制

#輸出:
#34
#()           

複制

** kwargs

還有一種動态參數,加了兩個星号則以字典的形式導入

#函數定義
def printinfo(arg1,**vardict):
    print('輸出:')
    print(arg1)
    print(vardict)
    
#調用
printinfo(34,a=45,b=32,c=12)           

複制

#輸出:
#34
#{'a': 45, 'b': 32, 'c': 12}           

複制

聲明函數時,參數中的* 可以單獨出現。

如果* 單獨出現,後面的參數必須以關鍵字傳入

def func(a,b,*,c):
    return a+b-c

func(3,2,4)   #非關鍵字傳入報錯           

複制

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-34-f69556d382a4> in <module>
      2     return a+b-c
      3 
----> 4 func(3,2,4)
TypeError: func() takes 2 positional arguments but 3 were given           

複制

關鍵字傳入正确

func(3,4,c=5)             

複制

#2           

複制

參數傳遞

python語言中,類型屬于對象,變量是沒有類型的,例如:

a=[1,2,3]

a='DataScience'

其中[1,2,3]是list類型,'DataScience'是string類型,變量a沒有類型,它隻是一個對象的引用(一個指針),可以指向list類型對象也可以指向string類型對象

可更改(mutable)與不可更改(immutable)對象

在 python 中,strings, tuples, 和 numbers 是不可更改的對象,而 list,dict 等則是可以修改的對象。
  • 不可變類型:變量指派 a=5 後再指派 a=10,這裡實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丢棄,不是改變a的值,相當于新生成了a。
  • 可變類型:變量指派 la=[1,2,3,4] 後再指派 la[2]=5 則是将 list la 的第三個元素值更改,本身la沒有動,隻是其内部的一部分值被修改了。

python 函數的參數傳遞:

  • 不可變類型:類似 c++ 的值傳遞,如 整數、字元串、元組。如fun(a),傳遞的隻是a的值,沒有影響a對象本身。比如在 fun(a)内部修改 a 的值,隻是修改另一個複制的對象,不會影響 a 本身。
  • 可變類型:類似 c++ 的引用傳遞,如 清單,字典。如 fun(la),則是将 la 真正的傳過去,修改後fun外部的la也會受影響

python 中一切都是對象,嚴格意義我們不能說值傳遞還是引用傳遞,我們應該說傳不可變對象和傳可變對象。

#傳不可變對象執行個體
#
#函數定義
def changeInt(a):
    a=10
    
#函數調用
b=5
changeInt(b)
print(b)           

複制

#5           

複制

執行個體中有 int 對象 2,指向它的變量是 b,在傳遞給 ChangeInt 函數時,按傳值的方式複制了變量 b,a 和 b 都指向了同一個 Int 對象,在 a=10 時,則新生成一個 int 值對象 10,并讓 a 指向它。

#傳可變對象執行個體
def changelist(List):
    #對傳入的清單進行擴充
    List.append([1,2,3,4])
    print('函數内取值:',List)
    return

#函數調用
List=['datascience']
changelist(List)
print('函數外取值:',List)           

複制

#函數内取值: ['datascience', [1, 2, 3, 4]]
#函數外取值: ['datascience', [1, 2, 3, 4]]           

複制

可變對象在函數裡修改了參數,那麼在調用這個函數的函數裡,原始的參數也被改變了。

傳入函數的和在末尾添加新内容的對象用的是同一個引用。

小作業

1.構造一個describe_pet函數,調用該函數輸入以下2隻寵物的資訊:

I have a cat. My cat's name is Monkey.

I have a lizard. My lizard's name is Cola.

2.編寫函數, 接收一個清單(包含10個整形)和一個整形k, 傳回一個新清單,要求: - 将清單下标k之前對應(不包含k)的元素逆序; - 将下标k及之後的元素逆序;

3.請用函數實作一個判斷使用者輸入的年份是否是閏年的程式

4.構造一個greeting函數,調用函數并使用循環,對輸入的參數傳回整理後的greeting資訊。

例如,在控制台分别輸入名字“Mary”和姓“Chen”,調用函數後輸出"Hello, Mary Chen!",并提示輸入下一組姓和名。直到控制台輸入姓或名為“end”時,程式結束。