python基礎(7)-函數&命名空間&做用域&閉包

函數

動態參數

  • *args

     1 def sum(*args):
     2     '''
     3     任何參數都會被args以元組的方式接收
     4     '''
     5     print(type(args))  # result:<class 'tuple'>
     6     sum = 0
     7     for i in args:
     8         sum += i
     9     return sum
    10 
    11 
    12 print(sum(1, 2, 3))  # result:6
    13 print(sum(*[1, 2, 3]))  # result:6
    14 # 12,13行等價
    15 # * 表示將這個列表按照順序打亂傳入
  • **kwargs

     1 def info(**kwargs):
     2     '''
     3     參數都會被kwargs以字典的方式接收
     4     :param kwargs:
     5     :return:
     6     '''
     7     print(type(kwargs))  # result:<class 'dict'>
     8     for key in kwargs:
     9         print(key, kwargs[key], end=' ')
    10     print()
    11 
    12 
    13 info(name='張三', age=12, gender='')
    14 info(**{'name': '李四', 'age': 14, 'gender': ''})  # ** 將字典按順序打亂傳入
    15 # result:   name 張三 age 12 gender 男
    16 #           name 李四 age 14 gender 女

默認參數

  • 經過默認參數輸出

     1 def name_sex_print(name, sex=''):
     2     print('姓名:{},性別:{}'.format(name, sex))
     3 
     4 name_sex_print('小強')
     5 name_sex_print('小兵')
     6 name_sex_print('小紅', '')
     7 # result:
     8 # 姓名:小強,性別:男
     9 # 姓名:小兵,性別:男
    10 # 姓名:小紅,性別:女
  • 默認參數陷阱

     1 def num_print(num_list=[]):
     2     num_list.append(1)
     3     print(num_list)
     4 
     5 num_print()
     6 num_print([])
     7 num_print()
     8 num_print()
     9 
    10 # result:
    11 # [1]
    12 # [1]
    13 # [1, 1]
    14 # [1, 1, 1]

    結論:若是默認參數的值是一個可變數據類型,那麼每一次調用函數的時候,若是不傳值就公用這個數據的資源python

函數的引用

  函數名實際上能夠看作指向函數在內存中的引用(和C#中委託很相像)閉包

  • 賦值

    1 def func1():
    2     print('print in func1')
    3     
    4 func2 = func1;
    5 func2()
    6 #result:
    7 # print in func1
  • 函數的傳遞

     1 def func1():
     2     print('print in func1')
     3 
     4 def func2(func):
     5     print('print in func2')
     6     func()
     7 
     8 func2(func1)
     9 
    10 # result:
    11 # print in func2
    12 # print in func1

     

命名空間

命名空間的概述

  • 內置命名空間

    1.python解釋器一啓動就能夠使用的變量及函數存放在內置命名空間內app

    2.內置的變量及函數在啓動解釋器的時候被加載進內存裏ide

    3.不能使用局部和全局命名空間的函數及變量函數

  • 全局命名空間(本身寫的非函數內部的代碼)

    1.是在程序從上到下被執行的過程當中依次加載進內存的ui

    2.放置了咱們設置的全部變量名和函數名spa

    3.能夠使用內置命名空間但不能使用局部命名空間中定義的變量及函數code

  • 局部命名空間

    1.定義在函數內部orm

    2.當調用函數的時候,纔會產生這個名稱空間,隨着函數執行的結束,這個命名空間就又消失了blog

    3.能夠使用全局及內置命名空間中的定義的變量及函數

三種命名空間的加載與取值順序

  • 加載順序

    內置命名空間(程序運行前加載)->全局命名空間(程序運行中:從上到下加載)->局部命名空間(程序運行中:函數調用時才加載)

  • 取值順序

    局部命名空間->全局命名空間->內置命名空間

做用域

做用域概述

  做用域就是做用範圍,按照生效範圍能夠分爲全局做用域和局部做用域

  • 全局做用域

    包含內置名稱空間、全局名稱空間,在整個文件的任意位置都能被引用、全局有效

  • 局部做用域

    局部名稱空間,只能在局部範圍(函數內部)生效

查看局部變量和全局變量

  使用locals()和globals()函數可查看局部和全局變量

  • locals()

    1 def locals_func():
    2     b = 2
    3     c = 3
    4     print(locals())
    5 
    6 locals_func()
    7 # result:
    8 # {'b': 2, 'c': 3}
  • globals()

    1 a=1
    2 b=2
    3 print(globals())
    4 #result:
    5 # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001D67208>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/learning/python/test/0828/locals.py', '__cached__': None, 'a': 1, 'b': 2}

     

做用域鏈

  • 就近原則

    在函數內部使用一個變量時,會由近到遠(由內而外)查找同名變量

     1 str = 'in globals'
     2 
     3 def fun1():
     4     str = 'in locals func1'
     5 
     6     def func2():
     7         str = 'in locals func2'
     8         print(str)
     9 
    10     func2()
    11 
    12 fun1()
    13 # result:
    14 # in locals func2
    View Code
     1 str = 'in globals'
     2 
     3 def fun1():
     4     str = 'in locals func1'
     5 
     6     def func2():
     7         # str = 'in locals func2'
     8         print(str)
     9     func2()
    10 
    11 fun1()
    12 # result:
    13 # in locals func1
    View Code
     1 str = 'in globals'
     2 
     3 def fun1():
     4     # str = 'in locals func1'
     5 
     6     def func2():
     7         # str = 'in locals func2'
     8         print(str)
     9 
    10     func2()
    11 fun1()
    12 # result:
    13 # in globals
    View Code 
  • nonlocal關鍵字

    使用要求:

    1.外部(非全局)必須有這個變量

    2.在內部函數聲明nonlocal變量以前不能再出現同名變量

     1 def func1():
     2     a = 1
     3 
     4     def func2():
     5         nonlocal a
     6         a = 2
     7 
     8     func2()
     9     print(a)
    10 
    11 func1()
    12 # result:
    13 # 2

閉包

閉包函數的定義

    內部函數包含對外部做用域而非全局做用域名字的引用,該內部函數稱爲閉包函數

1 def outer():
2     a = 1
3 
4     def inner():
5         print(a)
6     return inner
7 
8 func = outer()
9 func()

閉包函數的判斷

   可經過函數的__closure__屬性判斷該函數是不是一個閉包函數,若返回不是None,則就是閉包函數

def outer():
    a = 1
    def inner():
        b = a
        print(inner.__closure__)
    inner()
outer()
print(outer.__closure__)
#result:
# (<cell at 0x0000000000410108: int object at 0x000007FED797D420>, <cell at 0x0000000001DC82E8: function object at 0x00000000021CA730>)
# None

閉包的優缺點

  • 優勢

    1.可以讀取函數內部的變量

    2.讓這些變量一直存在於內存中,不會在調用結束後,被垃圾回收機制回收

  • 缺點

    1.因爲閉包會使函數中的變量保存在內存中,內存消耗很大,因此不能濫用閉包,解決辦法是,退出函數以前,將不使用的局部變量刪除

相關文章
相關標籤/搜索