what's the python之函數及裝飾器

what's the 函數?

  函數的定義:(return是返回值,能夠沒有,不過沒有的話就返回了None)閉包

def wrapper(參數1,參數2,*args,默認參數,**kwargs): '''註釋:函數功能和參數說明''' 函數體 return 返回值

  函數就是將要調用的內容打包裝進def()裏面,在不調用的狀況下只讀入內存不執行任何操做,若要調用時再一步一步進行。app

  函數的參數:有形參和實參兩種,形參指的是定義時寫在def後面的括號裏,實參指調用時纔會用到的代碼的實際的參數,形參就是在定義階段幫實參佔位置用的。函數

形參:位置形參、默認參數、動態參數、命名關鍵字參數spa

  位置形參:按照從左到右的順序定義,必須被傳值,多一個不行,少一個不行。(值常常變化時能夠將其定義爲位置形參)code

  默認參數:在定義函數時就已經爲形參賦值,調用階段能夠不用傳值(值基本不變時能夠用默認參數,調用階段就能夠忽略不傳值。好比礦工的性別、一個農村小學的學生的籍貫等等)。須要注意的因素:一:必須放在位置形參後面;二:默認參數一般要定義成不可變類型;三:默認參數只在定義階段被賦值一次。對象

  動態參數:實參的長度不固定是就用動態參數*args*和*kwargs,能夠接受任意類型blog

  命名關鍵字參數:定義在*後的形參,這類形參,必須被傳值,並且要求實參必須是以關鍵字的形式來傳值,如:內存

def register(*args,name='egon',age): print(args) print(name) print(age) # # register(name='egon',age=18)
register(1,2,2,3,age=10)

形參的定義順序爲:位置形參,默認參數,*args,命名關鍵字參數,**kwargs作用域

 

實參:位置實參、關鍵字參數(位置實參必須在關鍵字實參前面)域名

  位置實參:與位置形參相對應,統稱爲位置參數

  關鍵字參數:以key=value的形式指名道姓的傳值,能夠不用像位置實參同樣與形參一一對應

 


 

 

what's the 命名空間?

命名空間:內置命名空間、全局命名空間、局部命名空間

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

相對應的變量即全局變量和局部變量,局部變量的取值順序爲:

          在局部調用:局部命名空間->全局命名空間->內置命名空間;

          在全局調用:全局命名空間->內置命名空間

 

函數的嵌套:定義的函數中可再定義函數,內部的函數就是嵌套進去的函數,要記住凡是函數都有返回值return

做用域就是做用範圍,按照生效範圍能夠分爲全局做用域和局部做用域。函數的做用域關係在函數定義階段就已經固定,與調用位置無關,不管函數在何處調用,都須要回到定義階段去找對應的做用域關係

 

nonlocal關鍵字的運用:

# 1.外部必須有這個變量
# 2.在內部函數聲明nonlocal變量以前不能再出現同名變量
# 3.內部修改這個變量,若是外部有這個變量的只在第一層函數中生效
def f1(): a = 1
    def f2(): nonlocal a a = 2 f2() print('a in f1 : ',a) f1()

 

  函數名的本質是函數的內存地址,能夠被引用,能夠被看成容器類型的元素,能夠看成函數的參數和返回值。函數名能夠當普通變量使用。

注:

第一類對象(first-class object)指
1.可在運行期建立
2.可用做函數參數或返回值
3.可存入變量的實體。

 

 


 

閉包函數:在函數內部再定義一個函數,該內部函數包含對外部做用域,而不是對全局做用域名字的引用那麼該內部函數就叫閉包函數。(該函數即便不return也算閉包函數)

  閉包函數的特色就是自帶做用域,即始終攜帶其外部做用域的變量,即便在調用時在其外部再設置一個不一樣值的相同變量也不能改變其攜帶的變量的值。

定義閉包函數的基本形式:

def 外部函數名(): 內部函數須要的變量 def 內部函數(): 引用外部變量 return 內部函數

舉個小栗子:

def func():#如下縮進內容就是一個閉包函數
    name='alex'
    def bar(): print(name) return bar b=func()#由於func()return出了bar,因此b就等於bar
b()#這個b()就是bar(),就是一個閉包函數

 

查看閉包函數的一個方法:print(b.__closure__[0].cell_contents)  #若是結果是None,就說明不是閉包函數。

  b就是指閉包,__closure__指查看攜帶的變量的id,[0]指的是攜帶的第一個變量,cell_contents值的是查看攜帶的變量的值。

 

閉包函數的一個應用就是裝飾器,裝飾器的誕生是由於代碼的修改遵循開放封閉原則——已經實現功能的代碼不能被修改,可是能夠被擴展。就是由於不能被修改,因此纔有了裝飾器,以起到不修改源代碼的前提下對其效果進行修改的做用。

裝飾器的基本形式:

#裝飾器
def wrapper(func): def inner(*args,**kwargs):#定義函數的時候——*參數的聚合
        ret = func(*args,**kwargs)  #調用函數的時候——*參數的打散
        #func是被裝飾的函數,ret是被裝飾函數的返回值
        return ret #把被裝飾的函數的返回值返回給調用者
    return inner

調用裝飾器的方法是在要調用的函數的正上方@裝飾器,該方式名爲語法糖。

 

帶開關的裝飾器: 

def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''執行函數以前要作的''') re = func(*args,**kwargs) if flag: print('''執行函數以後要作的''') return re return inner return timer @outer(False)#參數是False表示關掉裝飾器,True表示開啓 # 開啓裝飾器就會執行代碼中的中文,也就是執行想要用裝飾器修改原來代碼的功能的部分
def func(): print(111) func()

 

 

一個函數能夠被多個裝飾器裝飾,一個裝飾器能夠裝飾多個不一樣的函數。

當一個函數被多個裝飾器裝飾時,首先要運行最上面的裝飾器,下面舉個小栗子:

def wrapper1(func):
    def inner():
        print('wrapper1 ,before func')
        func()
        print('wrapper1 ,after func')
    return inner

def wrapper2(func):
    def inner():
        print('wrapper2 ,before func')
        func()
        print('wrapper2 ,after func')
    return inner

@wrapper2#裝飾器裝飾了被裝飾事後的函數,因此對這個裝飾器而言下面的都是一個函數,即打印時的順序爲最上面的裝飾器先運行
@wrapper1#裝飾器裝飾了f()
def f():
    print('in f')

f()
'''
打印結果爲
wrapper2 ,before func
wrapper1 ,before func
in f
wrapper1 ,after func
wrapper2 ,after func
'''
相關文章
相關標籤/搜索