国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python裝飾器的另類用法

hqman / 3348人閱讀

摘要:今天我們一起探討一下裝飾器的另類用法。語法回顧開始之前我們再將裝飾器的語法回顧一下。例子本身只是演示了裝飾器的一種用法,但不是推薦你就這樣使用裝飾器。類裝飾器在以前,還不支持類裝飾器。

之前有比較系統介紹過Python的裝飾器(請查閱《詳解Python裝飾器》),本文算是一個補充。今天我們一起探討一下裝飾器的另類用法。

語法回顧

開始之前我們再將Python裝飾器的語法回顧一下。

@decorate
def f(...):
    pass

等同于:

def f(...):
    pass

f = decorate(f)

@語法的好處在于:

相同的函數名只出現一次,避免了f = decorate(f)這樣的語句。

可讀性更高,讓讀代碼的人一眼就明白函數被裝飾了哪些功能。

@call()裝飾器

假設你要創建一個整數平方的列表,你可以這樣寫:

>>> table = [0, 1, 4, 9, 16]
>>> len(table), table[3]
(5, 9)

也可以使用列表表達式,因為我們要實現比較簡單。

>>> table = [i * i for i in range(5)]
>>> len(table), table[3]
(5, 9)

但是假如這個列表的邏輯比較復雜的時候,最好是寫成一個方法,這樣會更好維護。

>>> def table(n):
...     value = []
...     for i in range(n):
...         value.append(i*i)
...     return value
>>> table = table(5)

注意看最后一句,是不是很符合裝飾器的語法規則?什么情況下你會寫這樣的代碼呢?

你需要把相對復雜業務寫成一個方法。

這個方法和返回值可以同名,而且你不希望對外公開此方法,只公開結果。

你想盡量使用裝飾器。(無厘頭的理由)

那么這時候@call()裝飾器就登場了。

def call(*args, **kwargs):
    def call_fn(fn):
        return fn(*args, **kwargs)
    return call_fn

這個裝飾器會把你傳入的參數送給目標函數然后直接執行

@call(5)
def table(n):
    value = []
    for i in range(n):
        value.append(i*i)
    return value

print len(table), table[3]  # 5 9

@call()裝飾器適用于任何函數,你傳入的參數會被直接使用然后結果賦值給同名函數。這樣避免了你重新定義一個變量來存儲結果。

@list 裝飾器

假如你有一個這樣一個生成器函數。

def table(n):
    for i in range(n):
        yield i

當你要生成n=5的序列時,可以直接調用。

table = table(5)
print table  # 

使用上節提到的@call()裝飾器,也能得到一樣的結果。

@call(5)
def table(n):
    for i in range(n):
        yield i

print table  # 

你還可以直接將其轉換成列表。(使用list(generator_object)函數)

@list
@call(5)
def table(n):
    for i in range(n):
        yield i

print table  # [0, 1, 2, 3, 4]

相信不少同學第一次看到這個用法應該是懵逼的。這等同于列表表達式,但是可讀性也許差了不少。例子本身只是演示了裝飾器的一種用法,但不是推薦你就這樣使用裝飾器。你這樣用也許會被其他同事拖到墻角里打死。

類裝飾器

在Python 2.6以前,還不支持類裝飾器。也就是說,你不能使用這樣的寫法。

@decorator
class MyClass(object):
    pass

你必須這樣寫:

class MyClass(object):
    pass

MyClass = decorator(MyClass)

也就是說,@語法對類是做了特殊處理的,類不一定是一個callable對象(盡管它有構造函數),但是也允許使用裝飾器。那么基于以上語法,你覺得類裝飾器能實現什么功能呢?

舉一個例子,ptest中的@TestClass()用于聲明一個測試類,其源代碼大致如此。

def TestClass(enabled=True, run_mode="singleline"):
    def tracer(cls):
        cls.__pd_type__ ="test"
        cls.__enabled__ = enabled
        cls.__run_mode__ = run_mode.lower()
        return cls
    return tracer

當我們在寫一個測試類時,發生了什么?

@TestClass()
class TestCases(object):
    # your test case ...

print TestCases.__dict__  # {"__module__": "__main__", "__enabled__": True, "__pd_type__": "test", "__run_mode__": "singleline", ...}

居然裝飾器的參數全都變成了變成這個類的屬性,好神奇!我們把語法糖一一展開。

class TestCases(object):
    pass

decorator = TestClass()
print decorator  # 

TestCases = decorator(TestCases)
print TestCases  # 

print TestCases.__dict__  # {"__module__": "__main__", "__enabled__": True, "__pd_type__": "test", "__run_mode__": "singleline", ...}

當裝飾器在被使用時,TestClass()函數會馬上被執行并返回一個裝飾器函數,這個函數是一個閉包函數,保存了enabledrun_mode兩個變量。另外它還接受一個類作為參數,并使用之前保存的變量為這個類添加屬性,最后返回。所以經過@TestClass()裝飾過的類都會帶上__enabled____pd_type__以及__run_mode__的屬性。

由此可見,類裝飾器可以完成和Java類似的注解功能,而且要比注解強大的多。

后記

裝飾器就是一個語法糖,當你看不懂一個裝飾器時,可以考慮將其依次展開,分別帶入。這個語法糖給了我們不少方便,但是也要慎用。畢竟可維護的代碼才是高質量的代碼。

關于作者:Python技術愛好者,目前從事測試開發相關工作,轉載請注明原文出處。

歡迎關注我的博客 http://betacat.online,你可以到我的公眾號中去當吃瓜群眾。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44238.html

相關文章

  • Python學習之路26-函數裝飾器和閉包

    摘要:初步認識裝飾器函數裝飾器用于在源代碼中標記函數,以某種方式增強函數的行為。函數裝飾器在導入模塊時立即執行,而被裝飾的函數只在明確調用時運行。只有涉及嵌套函數時才有閉包問題。如果想保留函數原本的屬性,可以使用標準庫中的裝飾器。 《流暢的Python》筆記本篇將從最簡單的裝飾器開始,逐漸深入到閉包的概念,然后實現參數化裝飾器,最后介紹標準庫中常用的裝飾器。 1. 初步認識裝飾器 函數裝飾...

    sunny5541 評論0 收藏0
  • python高級特性

    摘要:常規的使用來統計一段代碼運行時間的例子輸出結果總結其實是一門特別人性化的語言,但凡在工程中經常遇到的問題,處理起來比較棘手的模式基本都有對應的比較優雅的解決方案。 python的高級特性 名詞與翻譯對照表 generator 生成器 iterator 迭代器 collection 集合 pack/unpack 打包/解包 decorator 裝飾器 context manager ...

    yexiaobai 評論0 收藏0
  • Python】一文弄懂python裝飾器(附源碼例子)

    摘要:裝飾器的使用符合了面向對象編程的開放封閉原則。三簡單的裝飾器基于上面的函數執行時間的需求,我們就手寫一個簡單的裝飾器進行實現。函數體就是要實現裝飾器的內容。類裝飾器的實現是調用了類里面的函數。類裝飾器的寫法比我們裝飾器函數的寫法更加簡單。 目錄 前言 一、什么是裝飾器 二、為什么要用裝飾器 ...

    liuchengxu 評論0 收藏0
  • 每天一個設計模式之裝飾者模式

    摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...

    brianway 評論0 收藏0
  • 每天一個設計模式之裝飾者模式

    摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...

    shleyZ 評論0 收藏0

發表評論

0條評論

hqman

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<