第一節:函數入門與定義函數 
理解函數所謂函數,就是為一段實現特定功能的代碼“取”個名字,以后即可通過該名字來執行(調用)這段代碼 從邏輯上看,函數相當于一個黑匣子  定義函數的語法定義函數的三條鐵律函數需要幾個關鍵的、需要動態變換的數據,這些數據就應該定義成函數的參數 函數需要傳出去幾個重要的數據(就是調用該函數的人希望得到的數據),這些數據應該定義成返回值 函數內部的實現過程  函數的語法:  函數的語法
# 定義函數,無參數def first():    # 之前學習的定義變量、賦值、運算、分支、循環等全部都可以寫在函數里面    print('first 函數')    for i in range(5):        print(i)first()# 只要執行函數,函數體的代碼就可以被重復的調用(復用)first()first()# 函數定義,有一個參數 namedef hello(name):    print('hello 函數')    print('您好,' + name)hello('python')hello('java')# 函數定義,有2個參數 name, agedef info(name, age):    print('info函數')    print('name參數', name)    print('age參數', age)info(python, 90)info(java, 70)# 定義函數,有返回值def max(a, b):    r = a if a > b else b    # 返回值    return r# 返回值的意思,當程序調用函數之后,會得到N個值x = max(10, 20)print(x)x = max(30, 20)print(x)# print也是個函數,函數的嵌套print(max(20, 50))
為函數提供文檔只要把一段字符串放在函數聲明之后、函數體之前,這段字符串就是函數的說明文檔 Python內置的help()函數查看其它函數的幫助文檔 通過函數的_doc_屬性來查看函數的說明文檔  # 自定義說明文檔def test(a):    '''    test 函數的說明,這是一個簡單的函數    a-代表什么意義    return- 代表什么意義    '''    # 空語句    passprint(test.__doc__)help(test)
第二節:多返回值函數與遞歸函數 
多返回函數多返回值,本質就是返回元組 程序即可返回元組,也可直接返回多個值(系統會自動將其封裝成元組) 獲取多返回值函數的返回值時既可以用單個變量(元組)來獲取 也可以用多個變量獲取(元組解包)   import random# 希望該函數返回三個隨機的大寫字符def test():    # 生成三個隨機的大寫字符    c1 = chr(random.randint(65,90))    c2 = chr(random.randint(65,90))    c3 = chr(random.randint(65,90))        # 以元組的形式返回    return(c1, c2, c3)    # 程序自動封裝成元組    return c1, c2, c3# r就是一個元組r = test()print(r)print(test())# 多返回值函數,即可用多個變量來接收返回值,也可用單獨變量來接收返回值c1, c2, c3 = test()print(c1)print(c2)print(c3)
遞歸函數函數體內調用它自身,被稱為函數的遞歸 函數遞歸包含了一種隱式的循環,它會重復執行某段代碼,但是這種重復執行無需循環控制 遞歸函數的注意點  # 無限遞歸的例子def foo():    print('111')    print('222')    foo()foo()# 計算N的階乘def frac(n):    if n < 1:        print("n不能小于1")        return    elif n == 1:        return 1    else:        # n的階乘總是等于上一個階乘*n        # 函數調用自身        return frac(n-1) * n        # 該函數的結束點是n==1,因此要向n==1方向遞歸        print(frac(5))print(frac(6))
第三節:關鍵字參數與參數默認值 
關鍵字參數Python函數的參數名不是無意義的,Python允許調用函數時通過名字來傳入參數值 調用函數時支持兩種方式為參數指定值位置參數:必須按照順序為每個參數指定參數值 關鍵字參數(命名參數):按參數名為參數指定參數值   def info(name, age, height):    print("name:", name)    print("age:", age)    print("height:", height)    # 位置參數,按照順序傳遞參數info('fkjava', 24, 183)# 關鍵字參數(命名參數)# 關鍵字參數的優勢是 1:不需要按照順序 2:可讀性更高info(age=34, name='java', height=179)# 混合使用info('python', height=178, age=45)# 混合使用錯誤:關鍵字參數必須位于位置參數的后面info(name='python', 178, 45)
參數的默認值程序需要在定義函數的時候為一個或者多個形參指定默認值,這樣調用函數時就可以省略該形參傳入參數值,而是直接使用該形參的默認值 為形參指定默認值的語法格式如下:形參名 = 默認值  # 定義帶默認值的參數(一個參數有默認值)def info(age, name='python'):    print('age參數為:', age)    print('name參數為:', name)      # 為參數指定默認值之后,調用時候可省略指定的參數值,該參數使用默認值    info(23)info(45, 'abc')info(11, 'Java')# 混合方式info(19, name='bcd')# 定義帶默認值的參數(兩個參數有默認值)def info(age=19, name='python'):    print('age參數為:', age)    print('name參數為:', name)    info()info(20)# 如果你希望省略前面的參數指定參數值,后面的參數應該用關鍵字參數來傳入參數info(name='go')
第四節:參數搜集和逆向參數收集 
參數收集普通參數收集在形參前面加上一個星號(*),這樣就意味著該參數可接收多個參數值,多個參數值被當成元組傳入 參數收集的本質就是一個元組:Python會將傳給帶*參數的多個值收集成一個元組 Python允許個數可變的參數可以處于形參列表的任意位置,但是最多只能帶一個支持“普通”參數收集的參數 如果支持“普通”參數收集的形參位于前面,后面參數則需要使用關鍵字參數傳值   # books參數支持收集,它可接受多個參數值def test(num, *books):    print("num:", num)    print("books:", books)# 將多個值自動封裝成一個元組test(5, "go", "python", "java")def info(*names, msg):    for name in names:        print("%s, %s" % (name, msg))# 如果你要為參數收集后的參數傳入參數值,需要用關鍵字參數 info("孫悟空", "豬八戒", "牛魔王", msg="歡迎大家") # 否則所有參數都會被參數收集成元組 info("孫悟空", "豬八戒", "牛魔王", "歡迎大家")
關鍵字參數收集在參數前面添加兩個星號“**”,該參數支持關鍵字參數收集,收集的參數被當做dict處理 一個函數可同時支持普通參數收集和關鍵字參數收集  # books參數支持普通參數收集,它可接受多個參數值,socres支持關鍵字參數收集def test(num, *books, **socres):    print("num:", num)    print("books:", books)    print("socres:", socres)test(20, 'fkjava', 'python', 'swift', 語文=89, 數學=93)def info(*names, msg, **socres):    for name in names:        print("%s, %s" % (name, msg))    print(socres)# 程序知道msg參數將是傳給msg的,因此socres參數不會收集它# dict的參數收集,它只收集不能明確傳入的關鍵字參數info("孫悟空", "豬八戒", "牛魔王", msg="歡迎大家", 語文=89, 數學=93) 
def test(a, b):    print(a)    print(b)# 元組的逆向參數收集,以普通參數的形式為參數傳入參數值vals = (20, 40)# 調用函數時,元組不能自動解包# 默認情況下,元組是一個整體test(vals)# 這個語句是錯誤的# *對元組自動解包(逆向參數收集)test(*vals)# 列表的逆向參數收集,以普通參數的形式為參數傳入參數值msgs = ['aa', 'bb']test(*msgs)# 字典的逆向參數收集,以關鍵字參數的形式為參數傳入參數值# 簡單來說,**是將字典解析成關鍵字參數vals = {'a': 89, 'b': 93}test(**vals)
第五節:變量作用域 
理解變量作用域根據定義變量的位置,變量的作用域分為兩種:局部變量:在函數中定義的變量包括參數,都被成為局部變量 全局變量:在函數外面、全局范圍內定義的變量,被稱為全局變量   # 全局變量a = 35def info():    # 局部變量    b = 'fkjava'    # 正確,局部變量只能在當前函數內訪問    print(b)    # 正確,全局變量可以在任何函數內訪問    print(a)    def info1():    # 局部變量    c = 'java'    print(c)    # 正確,全局變量可以在任何函數內訪問    print(a)    # 錯誤,局部變量只能在定義局部變量的函數中使用    #print(b)    info()info1()
變量字典獲取變量字典globals():該函數返回全局范圍內搜所有變量組成的“變量字典” locals():該函數返回當前局部范圍內搜所有變量組成的“變量字典” vars(object):獲取指定對象的范圍內所有變量組成的“變量字典”,如果不傳入object參數,vars()和locals()作用完全相同   # 全局變量a = 35name = 'java'def info():    # 局部變量    b = 'fkjava'    # 正確,局部變量只能在當前函數內訪問    print(b)    # 正確,全局變量可以在任何函數內訪問    print(a)        # 局部變量組成的數組    print(locals())    def info1():    # 局部變量    c = 'java'    print(c)    # 正確,全局變量可以在任何函數內訪問    print(a)    # 錯誤,局部變量只能在定義局部變量的函數中使用    #print(b)        # 局部變量組成的數組    print(locals())# 全局變量組成的數組print(globals())  # locals獲取當前范圍內的所有局部變量# 因此你在全局范圍調用locals函數的時候,它返回全部的全局變量# 簡單來說,你在全局范圍內,用globals和locals函數效果是一樣的print(locals())   info()info1()
處理局部變量遮蔽全局變量全局變量默認可以在所有函數內訪問 如果在函數中定義了與全局變量同名的變量,此時就會發生局部變量的遮蔽(hide)全局變量的情形  # 解決方法一name = 'java'def info():    # 依然訪問全局變量name    print(globals()['name'])    # 在函數內對變量賦值,變成了定義新的name變量    name = 'python'    print(name)    info()# 全局變量name沒有改變print(name)# 解決方法二name = 'java'def info():    # 聲明作用:該函數中的name始終使用全局變量    global name    # 依然訪問全局變量name    print(name)    # 前面已經聲明了name始終是全局變量    # 因此此處不是重新定義局部變量    name = 'python'    print(name)    info()# 全局變量name會被改變print(name)
第六節:局部函數 
理解局部函數放在函數體內的函數稱為局部函數 在默認情況下,局部函數對外部是隱藏的,局部函數只能在其封閉(enclosing)函數內使用  def foo():    print('foo函數')    # 嵌套函數:在其他函數內定義的函數    def bar():        for i in range(5):            print('bar函數')    # 只能在foo函數內調用bar函數    bar()# 在此處調用bar函數出錯,局部函數只在它所在的封閉函數內有效# bar()foo()
封閉函數返回局部函數封閉函數可以返回局部函數,以便程序在其他作用域中使用局部函數 如果封閉函數沒有將局部函數返回出來,那么局部函數將只能在封閉函數內部調用  def foo():    print('foo函數')    # 嵌套函數:在其他函數內定義的函數    def bar():        for i in range(5):            print('bar函數')    # bar表示返回函數本身(函數也相當于一個值,是function類型的值)    # bar()表示調用(執行)函數    return bar    # foo函數的返回值時bar函數,因此此處是用變量r來保存bar函數r = foo()print(r)# 此時R引用bar函數本身,r的類型是functionprint(type(r))print('-' * 60)# 由于r是函數,因此程序可以調用它r()# 下面代碼看上去有點詭異# foo函數調用之后返回bar函數,bar函數也可調用foo()()
局部函數的變量遮蔽局部函數內的變量也會遮蔽它所在的封閉函數的局部變量 避免方法:可用nonlocal進行聲明  def test():    name = 'fkjava'    def  info():        print('info 函數')                # 聲明后面的name變量不是聲明新的局部變量,而是引用所在封閉函數的局部變量        nonlocal name        print('name:', name)        # 默認情況下,下面代碼是為info這個局部函數再次定義name局部變量        # 此時name局部變量就會遮蔽test函數的name變量        name = 'crazyit'        # 在沒有用nonlocal聲明之前,此時打印會出錯,用nonlocal聲明之后,程序正常        print('name:', name)    info()    print(name)test()
global與nonlocal總結作用大致相同,都是用來避免變量遮蔽 區別:global用于聲明訪問全局變量。nonlocal用于聲明訪問局部函數所在封閉函數內的局部變量  第七節:案例實操-定義計算N的階乘的函數 
實現方法方法一:使用循環計算階乘控制循環計數器從1循環到N 讓循環計數器與前一個結果相乘,直到循環計數器等于N就得到了N的階乘   def fract():    r = 1    if n < 1:        print('n不能小于1')        return     else:         for i in range(1, n + 1):             r *= i         return rprint(fract(5))
方法二:運用遞歸計算階乘經研究發現:N的階乘等于N乘以N-1的階乘,因此可借助于遞歸來實現 N為1時,N的階乘是1,保證遞歸有結束點  def fract():    if n < 1:        print('n不能小于1')        return     # 對于遞歸函數來說,必須保證在某個條件下,函數不再調用自身,遞歸結束     elif n == 1:         return 1     else:         # 遞歸:就是函數里面調用自身         return fract(n - 1) * n         print(fract(5))
方法三:調用reduce函數計算階乘Python在functools模塊提供了reduce()函數,該函數使用指定函數對序列對象進行積累 可通過help(reduce)查看該函數的用法:reduce(function, sequence[, initial])  import functoolsdef fn(x, y):    return x * y    def fract():    if n < 1:        print('n不能小于1')        return    else:        '''        # fn(ele1, ele2)->r        # fn(r,ele3)->r        # fn(r,ele4)->r        '''        # 方法一:        return functools.reduce(fn, range(1, n + 1))                # 方法二:        # lambda x ,y: x * y 的本質就是一個函數        return functools.reduce(lambda x ,y : x * y, range(1, n + 1))print(fract(5))
第八節:案例實操-定義計算矩陣轉置的函數 
使用循環進行轉置首先創建一個長度與原矩陣第一個元素長度相等的新列表 使用遍歷原矩陣的每個元素,再使用嵌套循環遍歷每個元素,將列表中的元素添加到新列表對應的列表元素中  matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]'''# 轉置就是行變列 列變行# 轉置之前1  2  3  45  6  7  89 10 11 12# 轉置之后1  5  92  6 103  7 114  8 12'''def printmatrix(m):    # 列表嵌套列表,因此ele也是列表    for ele in m:        # 打印一行        for e in ele:            print('%2d' % e, end=' ')     print(' ')     def transformmatrix(m) :    # m[0]有幾個元素,說明原矩陣有多少列    # 列轉成行    rt = [[] for i in m[0]]    for ele in m:        for i in range(len(ele)):            # rt[i]代表新矩陣的第i行            # ele[i]代表原矩陣當前行的第i列            rt[i].append(ele[i])     return rtprintmatrix(matrix)print('-' * 60)printmatrix(ransformmatrix(matrix))
使用zip()函數轉置zip函數的作用正是合并多個序列:多個序列第一個元素合并成第一個元素,多個序列第二個元素合并成第二個元素...... 運用逆向函數收集即可  matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def printmatrix(m):    # 列表嵌套列表,因此ele也是列表    for ele in m:        # 打印一行        for e in ele:            print('%2d' % e, end=' ')     print(' ')     def transformmatrix(m) :    # 逆向參數收集,將矩陣中多個列表轉換成多個參數,傳給zip    return list(zip(*m))printmatrix(matrix)print('-' * 60)printmatrix(ransformmatrix(matrix))
使用numpy模塊轉置numpy模塊提供transpose函數執行轉置,該函數的返回值是numpy的內置類型:array 調用array的tolist()方法可將array轉換成list列表  matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]def printmatrix(m):    # 列表嵌套列表,因此ele也是列表    for ele in m:        # 打印一行        for e in ele:            print('%2d' % e, end=' ')     print(' ')     def transformmatrix(m) :    # 使用numpy模塊的transpose函數進行轉置    import numpy    return numpy.transpose(m).tolist()printmatrix(matrix)print('-' * 60)printmatrix(ransformmatrix(matrix))
                            
總結 
                            
                                以上是生活随笔 為你收集整理的封装成vla函数_第四章:Python之函数 的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。