Python裝飾器的實現原理

  Python中的裝飾器是經過利用了函數特性的閉包實現的,因此在說裝飾器以前,咱們須要先了解函數特性,以及閉包是怎麼利用了函數特性的。

1.函數特性

  Python中的函數特性總的來講有四點:python

    1.函數做爲變量傳遞

def add(x):
    return x + 1

a = add  

    2.函數做爲參數傳遞

def add(x):
    return x + 1

def excute(f):
    return f(3)

excute(add)   

    3.函數做爲返回值

def add(x):
    return x + 1

def get_add():
    return add     

    4.函數嵌套及跨域訪問

def outer():
    x = 1
    def inner():
        print(x)         
    inner()

outer()

2.閉包的實現

  Python中的裝飾器是經過閉包實現的,簡單地講,閉包就是引用了外部變量的內部函數,而閉包的實現正是利用了以上函數特性,下面咱們來看看閉包是如何實現的:跨域

 

def outer(x):
    def inner():                  # 函數嵌套
        return x                  # 跨域訪問,引用了外部變量x

    return inner                  # 函數做爲返回值

closure = outer('外部變量')        # 函數做爲變量賦給closure
print(closure())                  # 執行閉包

#結果
外部變量

  在這個流程中,outer接收到'外部變量',傳給inner,做爲它return的參數,最後outer返回inner函數,返回的inner函數做爲變量傳遞給closure,最後執行closure這個函數對象,其實是執行了inner這個函數,返回了 '外部變量',這樣就實現了一個簡單的閉包。閉包

  上面這個閉包例子只用到了以前說的三個函數特性,函數做爲參數這個特性好像並無用上,下面作一下延伸,把outer的參數x用一個函數對象替代ide

def func():
    return '函數func'

def outer(x):
    def inner():                              # 函數嵌套
        return '戴了inner牌帽子的 ' + x()       # 跨域訪問,引用了外部變量x

    return inner                              # 函數做爲返回值

closure = outer(func)                         # 函數func做爲outer的參數;函數做爲變量賦給closure

print(func())                                 # 執行原始函數
print(closure())                              # 執行閉包

# 結果
函數func
戴了inner牌帽子的 函數func

  觀察上面的例子,從func()到closure(),函數func就是被裝飾了一番變成了clousre,分析一下具體過程:函數

  closure其實是outer(func),func做爲參數傳進outer,outer的子函數inner對func返回的結果進行了一番裝飾,返回了一個裝飾後的結果,最後outer返回inner,能夠說inner就是裝飾後的func,這就是一個函數被裝飾的過程,重點在於執行 outer(func) 這個步驟。spa

3.裝飾器語法糖@

  Python給咱們提供了語法糖 @,咱們想執行 outer(func) 的時候,只須要把outer函數@到func函數的上面就能夠了。code

def outer(x):
    def inner():
        return '戴了inner牌帽子的 ' + x()

    return inner

@outer
def func():
    return '函數func'

print(func())


#結果
戴了inner牌帽子的 函數func

   打印的結果跟咱們執行closure()的結果是同樣的,也就說明 加了outer裝飾器的func 等價於 outer(func),因此咱們很清楚地知道裝飾器@的做用是什麼了,就是拿來把被裝飾的函數做爲參數傳遞到裝飾器函數裏面加工的,最後執行被裝飾函數的時候,就至關於執行了一個加工後的函數。對象

以上就是Python中裝飾器的實現原理。blog

 

4.裝飾器的使用

  Python中裝飾器用處不少,下面寫一個例子感覺一下.get

  類中的私有屬性在類外部是沒法訪問的(就當沒法訪問好了,畢竟鬼叔是不推薦訪問的),而這時能夠在類中定義一個方法返回這個私有屬性而後在外部調用就能夠獲得這個私有屬性,可是這樣看起來就和正常的調用屬性的方式不同了(obj.屬性),這時候就能夠用@property來實現想要的效果.

class Person:
    def __init__(self,name,age):
        self.name = name
        if type(age) is int:
            self.__age = age
        else:
            print( '你輸入的年齡的類型有誤,請輸入數字')
    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self,a):
        '''判斷,你修改的年齡必須是數字'''
        if type(a) is int:
            self.__age = a
        else:
            print('你輸入的年齡的類型有誤,請輸入數字')

    @age.deleter
    def age(self):
        del self.__age


p1 = Person('帥哥',20)
print(p1.age)
del p1.age
用裝飾器實現屬性
相關文章
相關標籤/搜索