Python基礎(五)—函數(參數解析、global、遞歸)

形參和實參

形參即函數內使用的參數,實參即調用函數時的賦值,如下:

  def tmp(name):  # 形參
  	print(name)
  
  tmp('實參')

形參類型

  • 位置參數
    函數內使用到的形參爲關鍵參數,即調用該函數時必須傳入的參數。

  • 默認參數
    如:tmp(name=‘lz’,age),此時形參name即爲默認參數,默認值爲lz。

  • 可變參數
    如:tmp(*params),此時傳入的參數可以爲任意個參數,接收的是一個tuple()

  • 關鍵字參數
    如:tmp(**params),接受的是一個dict{}

  • 命名關鍵字參數
    如:tmp(name, age, , sex),此時後的sex即爲命名關鍵字參數,也就是調用時必須sex=’’,tmp(‘name’, ‘age’, sex=‘man’);若是tmp(name, age, *, sex=‘man’),此時調用是可以不傳入sex參數。

除了可變參數無法與命名關鍵字參數混合,其餘皆可混合使用,但是定義的順序必須爲:必選參數、默認參數、可變參數\命名關鍵字參數、關鍵字參數。

  def tmp(*params, name='lz', age='24'):
      for param in params:
          print('param:' + param)
  	print(name)
  	print(age)

  tmp(11, name='ss',age='22')  
  """
  	1.在調用含有可變參數的函數時,在可變參數後的形參進行設置默認值。
  	2.在調用函數時,儘量將調用函數內的參數寫爲:形參=實參,這樣增加代碼的可讀性,也使得增加函數調用的準確性。
  """

函數和過程

函數是用返回值的,過程是沒有返回值的。**對於python嚴格來說,只有函數,沒有過程!
函數也可以有多個返回值。
如下個例子:

  def hello():
  	print('hello python')

  tmp = hello()
  print(tmp)  # None
  print(type(tmp))  # <class 'NoneType'>

  # 返回多個至
  def returnTmp(name, age):
      return '名字:' + name, '年齡:' + str(age)

  name, age = returnTmp('lz', 24)

  print(name, age)  #名字:lz 年齡:24

可以看出函數都是用返回值的。這是因爲python都是動態的確定變量類型,其實就是沒有變量,只有名字。

全局變量和局部變量

函數內的即局部變量,函數外的即爲全局變量,函數外訪問局部變量會出錯。
函數可以訪問全局變量,但不要試圖去修改全局變量,因爲在函數內修改全局變量的話,python會在該函數新定義一個名字一樣的局部變量。

  def tmp():
      print(g_name)  # 報錯UnboundLocalError: local variable 'g_name' referenced before assignment,如果不加:g_name = 'lz1',則不報錯
      g_name = 'lz1'
      print(g_name)

  g_name = 'lz'
  tmp()
  print(g_name)
  # lz1
  # lz

global關鍵字

如果在函數內部試圖修改全局變量,Python會使用屏蔽的方式(shadowing機制)去保護全局變量,即創建該函數內的同名的局部變量,所以這樣就算修改,也只是修改了函數創建的局部變量,而全局變量卻沒有改變。
global關鍵字提供了函數內修改全局變量的方法。

 name = 'lz'
 def tmp():
     global name
     name = 'lzz'

 tmp()
 print(name)  # lzz,成功修改

遞歸

  • 遞歸形成有兩個條件:

    • 必須有一個明確的結束條件(遞歸出口);
    • 每次遞歸都是爲了讓問題規模變小

    遞歸其實就是分治思想。而遞歸層數一旦過多會導致棧溢出,並且相對循環,遞歸效率差很多。所以只是合適的地方使用遞歸,而不是每個能遞歸的問題都是用遞歸。
    以下直接使用一個遞歸與非遞歸的斐波那契數列的例子,來表達遞歸及兩者之間的效率差別。

  # 如果設置成35甚至更大,迭代結果立即出來,而遞歸則很慢
  def fab(n):
      n1 = 1
      n2 = 1
      n3 = 1
      if n < 1:
          print('輸入有誤')
          return -1
      while (n - 2) > 0:
          n3 = n2 + n1
          n1 = n2
          n2 = n3
          n -= 1
      return n3
  print(fab(20))

  def fab_recursion(n):
      if n < 1:
          return -1
      if n == 1 or n == 2:  # 結束條件
          return 1
      else:
          return fab(n-1) + fab(n-2)  #縮小問題
  print(fab_recursion(20))  

  • 漢諾塔
    漢諾塔:漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

    • 漢諾塔問題解釋
      我們假設三個指針爲 A、B、C
    • hanoi(1):如果只有一個盤子,直接A->C
    • hanoi(2,A,B,C):如果兩個盤子,即:A->B,A->C,B->C
    • 如果三個盤子,即:hanoi(2,A,C,B),A->C,hanoi(2,B,A,C)
      因此如果是n個盤子,就是這樣的過程:hanoi(n-1,A,C,B),A->C,hanoi(n-1,B,A,C)
    • 代碼實現:
      根據以上分析,可以得到以下代碼:
     def hanoi(n, A, B, C):
         if n == 1:
             print(A, '->', C)
         else:
             hanoi(n - 1, A, C, B)
             print(A, '->', B)
             hanoi(n - 1, B, A, C)
    
     hanoi(3, 'A', 'B', 'C')
    

個人博客:Loak 正 - 關注人工智能及互聯網的個人博客
文章地址:Python基礎(五)—函數(參數解析、global、遞歸)

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