python-函數與作用域

1、函數

(1)基本知識

  • 函數是對功能的封裝

  • 語法

    def function_name([parameters]):
        function_body
    
  • 返回值

    • 如果沒有return,或者return後面不跟數據,返回None
    • return後的語句不執行,即終止函數
    • return可以返回多個值,即return value1, value2, ...
      • 多個返回值返回的是一個元組
  • 參數:形參、實參和傳參

    • 形參:函數聲明時的未知的變量
      • 位置參數
      • 默認值參數:如def fuc(argu1, argu2 = None)
        • 當argu2沒有實參時,默認argu2=None
        • 注意:當默認值參數可變時(列表、指定、集合),默認值變量不會隨函數結束而消亡
      • 動態參數:即不定參數
    • 實參:函數調用的時候給的具體的值
      • 位置參數:按照形參順序傳遞實參
      • 關鍵字參數:按照形參名字傳遞實參,與位置無關
      • 混合參數:位置參數和關鍵字參數一起使用,先位置參數,後關鍵字參數(必須先位置參數)
    • 傳參:過程
  • 例子

    In [30]: def fuc(para1, para2, para3=None):
        ...:     print(para1)
        ...:     print(para2)
        ...:     print(para3)
        ...:     
    
    In [31]: fuc(1, 2)
    1
    2
    None
    
    In [32]: fuc(1, 2, 3)
    1
    2
    3
    
    In [33]: fuc(para3=1, para2=2, para1=3)
    3
    2
    1
    
    • def fuc(para1, para2, para3=None)
      • para1、para2、para3就是形參
      • 其中para1和para2爲位置參數,是有嚴格的順序的
      • para3爲默認值參數,即不給para3傳值時它有默認值
    • fuc(1, 2, 3)
      • 1、2、3就是實參,是具體傳遞的值
      • 這裏三個實參都是位置參數,即按順序給形參賦值
    • fuc(para3=1, para2=2, para1=3)
      • 這裏的1、2、3就是關鍵字參數,與位置無關,直接按形參的名字賦值

(2)參數傳遞

  • 動態傳參

    • def function(*argument_name) *表示動態傳參(位置參數),函數接收的數據類型是元組

      • 注意:使用這種動態傳參時要注意位置參數,合理順序是先位置參數,再動態參數,最後默認值參數
        (因爲默認值要生效就不能往形參傳值)
      • def fuc1(name, *food)
      • def fuc2(*food, name) fuc1和fuc2函數體相同
      • fuc1(a, b, c, d)fuc2(a, b, c, d)效果不同,因爲對於fuc2,food把a、b、c、d都接收了
      In [34]: def f1(a, *args):
          ...:     print(a)
          ...:     print(args)
          ...:     
      
      In [35]: def f2(*args, a):
          ...:     print(a)
          ...:     print(args)
          ...:     
      
      In [36]: f1(1, 2, 3)
      1
      (2, 3)
      
      In [37]: f2(1, 2, 3)
      ---------------------------------------------------------------------------
      TypeError                                 Traceback (most recent call last)
      <ipython-input-37-f8cc322696a9> in <module>()
      ----> 1 f2(1, 2, 3)
      
      TypeError: f2() missing 1 required keyword-only argument: 'a'
      
      • 可以看到使用f2時報錯了,因爲形參args將所有實參都吸收了
      • 由此我們知道*args參數一定要放到位置參數後面
    • def function(**argument_name) **表示動態傳參(關鍵字參數),函數接收的數據類型是字典

      In [38]: def fuc(a1=None, **kwargs):
          ...:     print(a1)
          ...:     print(kwargs)
          ...:     
      
      In [39]: fuc(name='aaa', age=20)
      None
      {'name': 'aaa', 'age': 20}
      
      In [40]: fuc(100, name='aaa', age=20)
      100
      {'name': 'aaa', 'age': 20}
      
      In [41]: fuc(name='aaa', age=20, 100)
        File "<ipython-input-41-86542b6e5b0a>", line 1
          fuc(name='aaa', age=20, 100)
                                 ^
      SyntaxError: positional argument follows keyword argument
      
      • 可以看到若實參使用關鍵字參數,且形參中沒有定義,則這些實參會被放到一個字典裏
      • 從上例中我們也可以得知**kwargs應該放在位置參數後面

(3)參數合理順序

  • 參數合理順序應該是:位置參數,*args,默認值參數,**kwargs(key word)

  • 例子如下

    In [42]: def fuc(a1, a2, *args, a3=None, a4=None, **kwargs):
        ...:     print(a1)
        ...:     print(a2)
        ...:     print(args)
        ...:     print(a3)
        ...:     print(a4)
        ...:     print(kwargs)
        ...:     
    
    In [43]: fuc(100, 200, 300, 400)  # 100->a1, 200->a2, 300和400->args
    100
    200
    (300, 400)
    None
    None
    {}
    
    In [44]: fuc(100, 200, a3=300, a4=400, a5=500, a6=600)
    # 100->a1, 200->a2, 300->a3, 400->a4, a5=500和a6=600->kwargs
    100
    200
    ()
    300
    400
    {'a5': 500, 'a6': 600}
    

(4)函數註釋

  • 函數的整體註釋可以這樣寫

    In [45]: def fuc():
        ...:     '''
        ...:     函數名稱:fuc
        ...:     函數功能:···
        ...:     入口參數:···
        ...:     出口參數:···
        ...:     '''
        ...:     pass
        ...: 
        ...: 
    
    In [46]: print(fuc.__doc__)
    
        函數名稱:fuc
        函數功能:···
        入口參數:···
        出口參數:···
        
    
    

(5)聚合(形參)

  • 接收所有參數:def fuc(*args, **kwargs)
  • *args,**kwargs相當於一個聚合的作用

(6)打散(實參)

  • 打散是用的*args的特性,例子如下

    In [52]: def fuc(*para):
        ...:     print(para)
        ...:     
    
    In [53]: l = [1, 2, 3]
    
    In [54]: fuc(l)
    ([1, 2, 3],)
    
    In [55]: fuc(l[0], l[1])
    (1, 2)
    
    In [56]: fuc(l[0], l[1], l[2])
    (1, 2, 3) 
    
  • 可以打散的類型有list、tuple、string、set、dictory

2、作用域

  • 名稱空間:

    • 1、內置名稱空間 2、全局名稱空間 3、局部名稱空間
    • 1->2->3(python解釋器運行順序)
  • 作用域命名空間

    • 全局作用域:內置名稱空間、全局名稱空間
    • 局部作用域:局部名稱空間
    • globals() 查看全局作用域的內容
    • locals() 查看當前的作用域的內容
  • 函數的嵌套:

    • 函數的定義可以嵌套
    • 訪問函數時要注意作用域
  • globalnonlocal

    • global value_name 可以把全局中的變量引入到函數內部或者在函數內部中創建一個全局變量
    • nonlocal value_name 從當前作用域往外層(全局作用域)方向尋找value_name,
      • 注意,不找全局作用域的變量,且只找離當前作用域最近的一層
  • 例子1

    In [11]: l = [1, 2, 4]
    
    In [12]: def f1():
        ...:     print(l)
        ...:     
    
    In [13]: f1()
    [1, 2, 4]
    
    In [14]: num = 100
    
    In [15]: def f2():
        ...:     print(num)
        ...:     
    
    In [16]: f2()
    100
    
    In [17]: def f3():
        ...:     a = 'hhhh'
        ...:     
    
    In [18]: print(a)
    ---------------------------------------------------------------------------
    NameError                                 Traceback (most recent call last)
    <ipython-input-18-bca0e2660b9f> in <module>()
    ----> 1 print(a)
    
    NameError: name 'a' is not defined
    
    • 局部作用域內可以訪問全局作用域裏的變量
    • 但是全局作用域內不可以訪問局部作用域裏的變量
  • 例子2

    In [28]: num = 100
    
    In [29]: def fuc():
        ...:     num = 200
        ...:     print(num)
        ...:     
    
    In [30]: fuc()
    200
    
    In [31]: print(num)
    100
    
    In [32]: def fuc2():
        ...:     global num
        ...:     num = 300
        ...:     
    
    In [33]: fuc2()
    
    In [34]: print(num)
    300
    
    • 在局部作用域內是無法修改全局作用域裏的變量的
    • 若要修改,必須在局部作用域內將變量聲明爲全局變量
    • 函數被執行後,變量才被修改(若不執行函數,則只是創建了函數,函數裏的語句並未執行)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章