Python函數

函數是一段可以重複使用的代碼,通過傳遞的參數返回不同的結果,函數能夠提高應用的模塊性和代碼的重複利用率。

博文大綱:
一、函數
二、變量的作用域
三、內建函數
四、特殊函數——lambda函數

一、函數

Python中的函數都是語句和表達式的集合。函數的用法並沒有限制,使用方法就像Python中其他值一樣,對於重複使用的代碼,需要編寫爲自定義函數以便於重複使用。

在CentOS 7系統(默認是Python 2.7.5)中實現!

函數可以分爲:

  • 無參函數;
  • 有參函數;

1.無參函數

(1)自定義無參函數,語法格式如下:

def 函數名稱():
    代碼塊
    return 表達式

以關鍵字def開始,後面跟函數名和小括號,以冒號開頭並縮進,最後使用return退出函數,有表達式則傳遞返回值,沒有則返回None。函數是以字母、數字和下劃線組成的字符串,但是不能以數字開頭。

無參函數的調用語法如下:

[變量 = ] 函數名稱()

使用賦值運算符“=”可以獲得函數的返回值,使用函數是必須先定義再調用,否則程序會出現錯誤。

實例:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def add():                            //定義函數
        op1=10
        op2=20
        rt=op1+op2
        print op1,'+',op2,'=',rt
        return
add()                                //調用函數
[root@localhost ~]# python 1.py                         //輸出結果
10 + 20 = 30

上述代碼中,定義了無參函數add(),輸出了10+20的值,return語句並沒有返回值,直接使用函數名add()進行了調用。

將上述代碼稍作修改,用return語句返回結果值,代碼如下:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def add():
        op1=10
        op2=20
        rt=op1+op2
        return rt
i=add()                      //將函數的返回值賦值給i
print i
[root@localhost ~]# python 1.py                //輸出結果
30

函數add()使用return語句返回相加的結果值,變量i接收函數add()返回的值。Python在處理返回值時,如果沒有return語句,會默認返回None,程序並不會報錯。

九九乘法表實例:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def a():
     for i in range(1,10):
        for j in range(1,i+1):
            print i, "*", j, "=" ,i*j,
        print "\t"
a()
[root@localhost ~]# python 1.py
1 * 1 = 1   
2 * 1 = 2 2 * 2 = 4     
3 * 1 = 3 3 * 2 = 6 3 * 3 = 9   
4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16   
5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25   
6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36    
7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49     
8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64  
9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81   

(2)使用函數時經常會犯一些錯誤,比如:

  • 函數的定義要先於函數的調用,否則會出錯;
  • 函數體的代碼是一個整體,要注意縮進;
  • 定義函數是要使用冒號,但調用時不可以使用冒號;

(3)編寫一個用戶登錄頁面的腳本,如下:

[root@localhost ~]# vim 1.py
#coding:utf-8  
kgc={}
def newuser():                                          //定義創建新用戶的無參函數
    prompt1 = 'login desired:'
    while True:
        name = raw_input(prompt1)
        if (kgc.has_key(name)):                             //has_key:用於判斷name鍵是否存在kgc字典中
            prompt1 = '--name taken,try another:'
            continue
        else:
            break
    pwd = raw_input('password:')
    kgc[name]=pwd
def olduser():                                     //定義已有賬號的無參函數
    name = raw_input('login:')
    pwd = raw_input('password:')
    password = kgc.get(name)                //獲取name在kgc字典中的值
    if password == pwd:
        print "ok"
    else:
        print "no"
def showmenu():                                  //定義列表菜單,調用上兩個無參函數
    prompt='''
        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:'''
    while True:
        choice = raw_input(prompt).strip()[0].lower()                          
                //strip()表示去除字符串錢的多餘字符,()表示空格
                //[0]表示字符串的第一個字符
                //lower()將字符變成小寫
        print '\n--You picked:[%s]' %choice
        if choice not in 'neq':
            print '--invalid option,try again--'
        else:
            if choice=='n':
                newuser()
            elif choice=='e':
                olduser()
            else:
                print 'quit'
                break
if __name__=='__main__':                           //定義程序入口
    showmenu()
[root@localhost ~]# python 1.py                                 //執行腳本

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:n                         //n表示新建用戶

--You picked:[n]
login desired:lzj
password:123

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:e                       //表示已有賬號登錄

--You picked:[e]
login:lzj
password:123
ok                                            //登錄成功,顯示ok

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
      Enter choice:q                          //q表示退出腳本

--You picked:[q]             
quit

2.帶參函數

(1)帶參函數的語法格式:

def 函數名稱(形式參數列表):
    代碼塊
    return [表達式]

通過語法,可以看出帶參函數與無參函數的區別就是在函數名稱後的小括號中有形式參數列表,參數列表實際上只是佔位符,用於體現參數的個數,每個參數都沒有提供具體的數值。

帶參函數的調用語法如下:

[變量 = ] 函數名稱( 參數列表)

調用時只需要在每個參數傳遞對應的實際數值,就可以完成函數的調用。

實例:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def add(x,y):
        return x+y
print add(1,2)
[root@localhost ~]# python 1.py
3

上述代碼中定義了函數add(),它有兩個形式參數x和y,在函數的語句塊中可以使用x和y,和使用變量是類似的。通過函數名add()和實際的參數值1和2進行調用,所以返回值是3.

(2)當調用函數時,傳遞的實際參數值是根據位置來跟函數定義的參數表匹配的,如下:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def add(x,y):
        print x,y
add(1,2)
add(10,20)
[root@localhost ~]# python 1.py
1 2
10 20

在函數add(x,y)中,輸出x,y值,x在前,y在後。調用add(1,2)時,x的值是1,y的值是2;當調用add(10,20)時,x的值是10,y的值是20,所以在最後的輸出結果是不同的。

(3)當程序比較繁瑣時,參數的順序是很難記住的,可以使用關鍵字參數。關鍵字參數實在調用函數時,明確指定參數值付給那個形參,語法格式如下:

函數名稱(形參1=實參1,形參2=實參2……)

實例:

[root@localhost ~]# vim 1.py

#coding:utf-8  
def add(x,y):
        print x,y
add(x=1,y=2)
add(y=10,x=20)
[root@localhost ~]# python 1.py
1 2
20 10

在調用的過程中,明確指定了實參是形參的對應關係,所以在輸出的時候,就不會因爲位置的原因,而錯亂順序。

(4)調用普通參數函數時,傳入的參數個數必須和聲明的參數個數一致。但關鍵字參數有一個特殊的作用,可以在定義函數時設置關鍵字參數的默認值,此時傳入函數的參數就可以和聲明的參數個數不一致了。

實例:

[root@localhost ~]# vim 1.py
#coding:utf-8  
def add(x,y=100):
        print x,y
add(x=100)
add(100,200)
[root@localhost ~]# python 1.py
100 100
100 200

定義時參數y的默認值是6,調用時,可以不傳遞y的值,只傳遞x的值即可,直接傳值或使用參數名並賦值都可以;如果定義了y的值,則y的默認值將不生效。

注意:定義關鍵字參數默認值時需要注意,位置參數必須出現在默認參數之前,比如以下的函數定義時錯誤的:

#coding:utf-8  
def add(x=1,y):
        print x,y
add(x=100)
add(100,200)

(5)編寫一個計算器程序
需求如下:

  • 完成一個計算器的程序,用戶輸入兩個數字和運算符,做加減乘除運算,
  • 爲了使程序結構清晰,需要編寫兩個函數,一個是用來處理加減乘除運算,一個是用來處理字符串和數值轉換。
#完整代碼如下:
def operator(op1,op2,opfu):
    if opfu not in '+-*/':
        return -1
    if opfu =='+':
        result = op1+op2
    elif opfu =='-':
        result = op1-op2
    elif opfu =='*':
        result = op1*op2
    elif opfu =='/':
        if op2 == 0:
            print '錯誤,除數不能爲0!/n'
            result = None
        else:
            result = op1/op2
    return result
def convert(op):
    flag = True
    for ch in op:
        if ch not in '1234567890':
            flag = False
            break
        if flag == True:
                return int(op)
        else:
            return None
if __name__=='__main__':
    str1 = '請輸入第一個數:\n'
    strfu = '請輸入一個算數運算符:\n'
    str2 = '請輸入第二個數:\n'
    while True:
        print '需要退出程序,請輸入字母q'
        opp1 = raw_input(str1)
        ch = opp1.strip()[0].lower()
        if ch == 'q':
            break
        op1 = convert(opp1)
        if op1 ==None:
            print '輸入錯誤,請輸入整數!\n'
            continue
        while True:
            opfu = raw_input(strfu)
            if opfu in '+-*/':
                break
            else:
                print '運算符輸入錯誤'
                continue
        while True:
            op2 = convert(raw_input(str2))
            if op2 == None:
                print "輸入錯誤,請輸入整數!\n"
                continue
            else:
                break
        result = operator(op1,op2,opfu)
        if result <> None:
            print "計算%d %s %d = %d \n" %(op1,opfu,op2,result)
print '程序退出了'
#執行結果如下:
需要退出程序,請輸入字母q
請輸入第一個數:
10
請輸入一個算數運算符:
*
請輸入第二個數:
2
計算10 * 2 = 20 

需要退出程序,請輸入字母q
請輸入第一個數:
q
程序退出了

現在對上述代碼進行分段解釋:
第一段代碼:

def operator(op1,op2,opfu):
    if opfu not in '+-*/':
        return -1
    if opfu =='+':
        result = op1+op2
    elif opfu =='-':
        result = op1-op2
    elif opfu =='*':
        result = op1*op2
    elif opfu =='/':
        if op2 == 0:
            print '錯誤,除數不能爲0!/n'
            result = None
        else:
            result = op1/op2
    return result

在上面代碼中,位置1處定義了函數operator(op1,op2,opfu),參數op1表示運算符前面的數值,op2表示運算符後面的數值,opfu表示運算符,然後先判斷opfu是不是“+-*/”中的其中一個,如果不是,返回值是-1,表示程序出錯。在接下來就是判斷是哪個運算符號,就進行哪種運算處理。但是在判斷除法運算符時,需要加一個條件,就是除數不能是0,因爲除數是0在數學上是沒有意義的,最後只要把運算的結果返回即可。

第二段代碼:

def convert(op):
    flag = True
    for ch in op:
        if ch not in '1234567890':
            flag = False
            break
        if flag == True:
                return int(op)
        else:
            return None

在上面的代碼中,首先定義了一個布爾型變量flag,用於判斷數值的有效性,在for循環語句中,op是傳進來的字符串,使用for循環判斷它的每一個字符是不是在“1234567890”中,如果有一個不再,說明這個字符串不能轉換爲數值,flag的值爲False,退出循環,否則flag的值不變,還是True,說明字符串可以轉換爲數值型。然後接下來做了相應的判斷,把字符串op轉換爲了整型,使用的是int()函數。最後是如果不能轉換爲整型,返回的是None。

第三段代碼:

if __name__=='__main__':
#以下是定義三個字符串的提示文字
    str1 = '請輸入第一個數:\n'
    strfu = '請輸入一個算數運算符:\n'
    str2 = '請輸入第二個數:\n'
#下面是主體代碼的無限循環操作,可以用來進行多次計算
    while True:
        print '需要退出程序,請輸入字母q'
#以下是判斷當鍵盤輸入q時,就退出程序
        opp1 = raw_input(str1)
        ch = opp1.strip()[0].lower()
        if ch == 'q':
            break
#對輸入的第一個字符串進行數值轉換操作,convert()返回是None,說明不能轉換,使用continue進入到下一次循環重新輸入。
        op1 = convert(opp1)
        if op1 ==None:
            print '輸入錯誤,請輸入整數!\n'
            continue
#等待輸入運算符,如果是“+-*/”中的一個,使用break結束循環,否則執行continue,重新輸入
        while True:
            opfu = raw_input(strfu)
            if opfu in '+-*/':
                break
            else:
                print '運算符輸入錯誤'
                continue
#下面是輸入第二個數值,同樣需要做轉換操作,如果不能轉換就需要重新輸入
        while True:
            op2 = convert(raw_input(str2))
            if op2 == None:
                print "輸入錯誤,請輸入整數!\n"
                continue
            else:
                break
#下面就是調用函數operator進行運算,result不等於None就說明運算是正常的,顯示出運算結果
        result = operator(op1,op2,opfu)
        if result <> None:
            print "計算%d %s %d = %d \n" %(op1,opfu,op2,result)
print '程序退出了'

二、變量的作用域

作用域是指變量在程序中的應用範圍,而變量聲明的位置決定它的作用域,Python按作用域區分有局部變量和全局變量。

1、全局變量:

全局變量是指在一個模塊中最高級別的變量有全局作用域,除非被刪除,否則存活到程序運行結束,所有函數都能訪問全局變量。

2、局部變量:

局部變量是指定義在函數內的變量有局部作用域,依賴於定義變量的函數現階段是否處於活動狀態,調用函數時,局部變量產生,暫時存在,一旦函數執行完成,局部變量就不存在了。

局部變量的作用域僅限於定義它的函數,全局變量的作用域在整個模塊內部都是可見的。在同一個函數中,不允許有同名的局部變量,在不同函數中,可以有同名的局部變量。在同一個程序中,全局變量和局部變量同名時,局部變量具有更高的優先級。

示例:

#代碼如下:
def addage(age):
    age += 1
    print 'addage():_age=%d age=%d' %(_age,age)
    return age
_age = input('請輸入年齡:\n')
rt = addage(_age)
print 'main():_age = %d'%_age
print 'main(): rt=%d' %rt
#執行結果如下:
請輸入年齡:
10            #輸入一個“10”
addage():_age=10 age=11
main():_age = 10
main(): rt=11

在上面的代碼中,函數addage(age)中定義了局部變量age,在全局範圍定義了全局變量_age。_age的值是由我們鍵盤輸入的,它在全局都生效,所以在addage(age)函數中也可以對它進行引用。當鍵盤輸入是10時,_age的值是10,調用“rt=addage(_age)”,就是把全局變量_age的值10傳給了函數,此時addage(age)的局部變量age的值也是10,執行age += 1後,age值成爲了11,而全局變量_age的值不發生變化,打印輸出“_age=10 age=11”,函數的返回值age的值是11,由rt接收,所以打印“_age=10,rt=11”

通過上面的代碼示例,可以看出Python採用的是值傳遞的方式,但實際上並不是這樣。Python採用的是值傳遞和引用傳遞相結合的方式,當傳遞可變對象時(如字典或者列表),相當於傳引用,而不可變對象(如數字、字符或元組)就是值傳遞。上面傳遞的是字符串,所以是值傳遞的方式。

在Python中儘量不使用全局變量,因爲程序中可以自由的訪問全局變量,其他人並不知道哪個變量是全局變量,非常容易出現引用錯誤,這種錯誤也很難發現和更正的。

局部變量只有在局部中才能使用,其他範圍是訪問不到的,如上面的代碼彙總age是局部變量,在全局範圍就引用不到,比如在上面程序中加上下面這行代碼,就會報錯。

#在上面代碼末尾加上下面這段代碼:
 # ....................省略部分內容
print 'main():age = %d'%age
#執行結果如下:
請輸入年齡:
10
addage():_age=10 age=11
main():_age = 10
main(): rt=11

Traceback (most recent call last):     
  File "C:/Users/Administrator/Desktop/aa.py", line 9, in <module>
    print 'main():age = %d'%age 
NameError: name 'age' is not defined      #提示age沒有定義

錯誤顯示age沒有定義,說明在全局範圍age是訪問不到的,這個問題可以使用global關鍵字解決,global的作用是聲明變量爲全局變量,即使變量定義在函數內部,加上global後,也可以在全局範圍訪問,修改後的代碼如下:

def addage(num):
    global age
    age = num+1
    print 'addage():_age=%d age=%d' %(_age,age)
    return age
_age = input('請輸入年齡:\n')
rt = addage(_age)
print 'main():_age = %d'%_age
print 'main(): rt=%d' %rt
print 'main():age = %d'%age

上面代碼中做了一些調整,主要使用了global定義age,最後在全局引用age時,可以正常使用。

在函數中,使用global語句聲明的全局變量名不能與其中的局部變量重名,而且儘量要避免在函數中使用global定義全局變量,減少程序的不可預知性。

三、內建函數

Python除了本身的語法結構,還提供了常用的內建函數,內建函數是我們經常使用到的方法,可增加程序編寫的效率,如float()函數就是內建函數。內建函數是自動加載的,Python的解釋器可以識別,它不需要導入模塊,不必做任何操作,不需要引用就可以調用。

1、abs()函數能夠返回一個數字的絕對值,即整數,如下:

>>> abs(10)
10
>>> abs(-10)
10
>>> bb = -3
>>> abs(bb)
3

2、bool()函數返回值是TRUE或FALSE,它是布爾值的簡寫,可以用來判斷字符是否爲空,如下:

>>> bool()    #無參數時返回False
False
>>> bool(0)
False
>>> bool(-3)
True
>>> bool(None)
False
>>> bool('xyz')
True
>>> bool('11,22')
True

3、float()函數用於轉換數據爲float(浮點)類型,字符串和數字都可以轉換爲float類型,如果不能轉換,就會報錯,如下:

>>> float(25)
25.0
>>> float(3)
3.0
>>> float(99.589456)
99.589456
>>> float('99.589456')
99.589456

4、int()函數可以將數據轉換爲整數,如下:

>>> int(199.99)     #浮點數
199
>>> int('100')     #字符串
100
>>> int('99.99')     #字符串,字符串中只能是整數格式,如果是浮點型就會報錯

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    int('99.99')
ValueError: invalid literal for int() with base 10: '99.99'

5、range()函數可以生成一個列表,如下:

>>> range(0,5)
[0, 1, 2, 3, 4]
>>> range(0,30,3)     #第三位的數字代表步長,是可選參數
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
>>> range(30,0,-3)
[30, 27, 24, 21, 18, 15, 12, 9, 6, 3]
>>> for i in range(0,5):
    print i

0
1
2
3
4

6、sum()函數可以對列表中元素求和,如下:

>>> num = range(0,500,50)   #定義一個元組
>>> num          #查看元組中的值
[0, 50, 100, 150, 200, 250, 300, 350, 400, 450]
>>> print (sum(num))    #對元組中的值進行求和操作
2250

7、max()函數可以返回列表、元組或字符串中最大的元素,如下:

>>> num = [6,2,12,7,65]
>>> max(num)
65
>>> str = 'a,d,g,c,D,U,A,N,G'
>>> max(str)
'g'
>>> max(1000,650,98,2689)
2689

8、min()函數返回列表、元組或字符串中值最小的元素,和max()正好相反,如下:

>>> min(10,9,7)
7

9、dir()函數可以返回關於任何值的相關信息,可以用於任何對象,包括字符串、數字、函數、模塊、對象和類。相當於幫助手冊。如下:

>>> dir()                #無參數時,返回當前範圍內的變量
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '_age', 'addage', 'age', 'bb', 'i', 'num', 'rt', 'str']
>>> dir(rt)                #帶參時,返回的是參數的屬性、方法列表
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']

10、eval()函數是可以計算表達式的值。如下:

>>> eval('100*9')
900
>>> eval(raw_input("請輸入表達式:"))
請輸入表達式:8+9*2-3
23

11、len()函數返回一個對象的長度,如下:

>>> len('lvjianzhao')       #字符串
10
>>> language = ['python','java','c#','vb']       #列表
>>> len(language)
4
>>> person = {'zhangsan':'123','lisi':'234','wangwu':'345'}    #定義一個字典
>>> len(person)
3

四、特殊函數——lambda函數

lambda函數的作用是創建匿名函數,是一種聲明函數的特殊方式。
lambda函數的語法格式如下:

lambda params:expr

其中params相當於函數接受的參數列表,expr是函數返回值的表達式。

示例:

#代碼如下
def sum1(x,y):
    return x+y
sum2 = lambda x,y:x+y
print sum1(1,2)
print sum2(1,2)
#執行結果如下
3
3

實現的是相同的功能,但lambda函數更加簡潔,只用一條語句實現,所以lambda也稱爲lambda表達式,使用lambda只能是表達式,不能包含if、for等條件循環語句,對於不需要複用、簡單的匿名函數,使用lambda能起到很好的效果。

———————— 本文至此結束,感謝閱讀 ————————

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章