真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么理解Python裝飾器-創(chuàng)新互聯(lián)

這篇文章主要介紹“怎么理解Python裝飾器”,在日常操作中,相信很多人在怎么理解Python裝飾器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解Python裝飾器”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

目前創(chuàng)新互聯(lián)建站已為數(shù)千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、新林網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

前言

或許你已經(jīng)用過裝飾器,它的使用方式非常簡單但理解起來困難(其實(shí)真正理解的也很簡單),想要理解裝飾器,你需要懂點(diǎn)函數(shù)式編程的概念,python函數(shù)的定義以及函數(shù)調(diào)用的語法規(guī)則等,雖然我沒法把裝飾器變得簡單,但是我希望可以通過下面的步驟讓你由淺入深明白裝飾器是什么。假定你擁有最基本的Python知識,本文闡述的東西可能對那些在工作中經(jīng)常接觸Python的人有很大的幫助。

1、函數(shù)(Functions)

在Python里,函數(shù)是用def關(guān)鍵字后跟一個(gè)函數(shù)名稱和一個(gè)可選的參數(shù)表列來創(chuàng)建的,可以用關(guān)鍵字return指定返回值。下面讓我們創(chuàng)建和調(diào)用一個(gè)最簡單的函數(shù):

>>> def foo():
... return 1
>>> foo()
1

該函數(shù)的函數(shù)體(在Python里將就是多行語句)是強(qiáng)制性的并且通過縮進(jìn)來表明。我們可以通過在函數(shù)名后面添加雙括號來調(diào)用函數(shù)。

2、作用域(Scope)

在Python中,每個(gè)函數(shù)都會創(chuàng)建一個(gè)作用域。Pythonistas也可能稱函數(shù)擁有它們自己的命名空間(namespace)。這意味著當(dāng)在函數(shù)體里遇到變量名時(shí),Python首先在該函數(shù)的命名空間中查找,Python包含了一些讓我們查看命名空間的函數(shù)。讓我們寫一個(gè)簡單的函數(shù)來探查一下local和global作用域的區(qū)別。

>>> a_string = "This is a global variable"
>>> def foo():
... print locals()
>>> print globals() # doctest: +ELLIPSIS
{..., 'a_strin': 'This ia a global variable'}
>>> foo() # 2
{}

內(nèi)建的globals函數(shù)返回一個(gè)字典對象,它包含所有Python知道的變量名(為了清楚明了起見,我已經(jīng)忽略了一些Python自動創(chuàng)建的變量)。在#2處我調(diào)用了函數(shù)foo,它將函數(shù)內(nèi)部的local namespace里的內(nèi)容打印了出來。正如我們看到的foo函數(shù)擁有自己的獨(dú)立namespace,現(xiàn)在它還是空的。

3、變量解析規(guī)則(variable resolution rules)

當(dāng)然,這并不意味著在函數(shù)內(nèi)部我們不能訪問全局變量。Python的作用域規(guī)則是,變量的創(chuàng)建總會創(chuàng)建一個(gè)新的local變量,但是變量的訪問(包括修改)會先查找local作用域然后順著最鄰近的作用域去尋找匹配。因此,如果我們修改foo函數(shù)來讓它打印global變量,結(jié)果就會像我們希望的那樣:

>>> a_string = "This is global variable"
>>> def foo():
... print a_string # 1
>>> foo()
This is a global variable

在#1處,Python在函數(shù)中尋找一個(gè)local變量,但是沒有找到,然后在global變量中找到了一個(gè)同名的變量。

另一方面,如果我們嘗試在函數(shù)里給global變量賦值,結(jié)果將不如我們所愿:

>>> a_string = 'This is a global variable"
>>> def foo():
... a_string = "test" # 1
... print locals()
>>> foo()
{'a_string': 'test'}
>>> a_string # 2
'This is a global variable'

正如我們所見,全局變量可以被訪問到(如果是可變類型,其甚至可以被改變),但是(默認(rèn)情況下)不能被賦值。在函數(shù)內(nèi)部的#1處我們實(shí)際上創(chuàng)建了一個(gè)新的local變量,它和全局變量擁有相同的名字,它將全局變量給覆蓋了。我們可以通過在foo函數(shù)內(nèi)部打印local namespace來發(fā)現(xiàn)到它已經(jīng)有了一個(gè)條目,通過對函數(shù)外部的#2處的輸出結(jié)果我們可以看到,變量a_string的值根本就沒有被改變。

4、變量的生命周期(Variable lifetime)

也要注意到,變量不僅“生活在”一個(gè)命名空間里,它們還有生命周期。考慮下面的代碼:

>>> def foo():
... x = 1
>>> foo()
>>> print x # 1
Traceback (most recent call last):
...
NameError: name 'x' is not defined

在#1處不僅因?yàn)樽饔糜蛞?guī)則引發(fā)了問題(盡管這是出現(xiàn)了NameError的原因),而且也出于在Python和許多其它語言里的函數(shù)調(diào)用實(shí)現(xiàn)的原因。此處,我們沒有任何可用的語法來獲取變量x的值——字面上是不存在的。每次當(dāng)調(diào)用foo函數(shù)時(shí),它的namespace被重新構(gòu)建,并且當(dāng)函數(shù)結(jié)束時(shí)被銷毀。

5、函數(shù)的參數(shù)(Function parameters)

Python允許我們向函數(shù)傳遞參數(shù)。參數(shù)名成為了該函數(shù)的local變量。

>>> def foo(x):
... print locals()
>>> foo(1)
{'x': 1}

Python有許多不同的定義和傳遞函數(shù)參數(shù)的方法。要想更詳細(xì)深入地了解請參照the Python documentation on defining functions。這里我展示一個(gè)簡版:函數(shù)參數(shù)既可以是強(qiáng)制的位置參數(shù)(positional parameters)或者是命名參數(shù),參數(shù)的默認(rèn)值是可選的。

>>> def foo(x, y=0): # 1
... return x - y
>>> foo(3, 1) # 2
2
>>> foo(3) # 3
3
>>> foo() # 4
Traceback (most recent call last):
...
TypeError: foo() takes at least 1 argument (0 given)
>>> foo(y=1, x=3) # 5
2

在#1處我們定義了一個(gè)帶有一個(gè)位置參數(shù)x和一個(gè)命名參數(shù)y的函數(shù)。正如我們看到的,在#2處我們可以通過普通的值傳遞來調(diào)用函數(shù),即使一個(gè)參數(shù)(譯者注:這里指參數(shù)y)在函數(shù)定義里被定義為一個(gè)命名參數(shù)。在#3處我們可以看到,我們甚至可以不為命名參數(shù)傳遞任何值就可以調(diào)用函數(shù)——如果foo函數(shù)沒有接收到傳給命名參數(shù)y的值,Python將會用我們聲明的默認(rèn)值0來調(diào)用函數(shù)。當(dāng)然,我們不能漏掉第一個(gè)(強(qiáng)制的,定好位置的)參數(shù)——#4以一個(gè)異常描述了這種錯(cuò)誤。

都很清晰和直接,不是嗎?下面變得有點(diǎn)兒讓人疑惑——Python也支持函數(shù)調(diào)用時(shí)的命名參數(shù)而不只是在函數(shù)定義時(shí)。請看#5處,這里我們用兩個(gè)命名參數(shù)調(diào)用函數(shù),盡管這個(gè)函數(shù)是以一個(gè)命名和一個(gè)位置參數(shù)來定義的。因?yàn)槲覀兊膮?shù)有名字,所以我們傳遞的參數(shù)的位置不會產(chǎn)生任何影響。 相反的情形當(dāng)然也是正確的。我們的函數(shù)的一個(gè)參數(shù)被定義為一個(gè)命名參數(shù)但是我們通過位置傳遞參數(shù)—— #4處的調(diào)用foo(3, 1)將一個(gè)3作為第一個(gè)參數(shù)傳遞給我們排好序的參數(shù)x并將第二個(gè)參數(shù)(整數(shù)1)傳遞給第二個(gè)參數(shù),盡管它被定義為一個(gè)命名參數(shù)。

Whoo!這就像用很多話來描述一個(gè)非常簡單的概念:函數(shù)的參數(shù)可以有名稱或者位置。

6、內(nèi)嵌函數(shù)(Nested functions)

Python允許創(chuàng)建嵌套函數(shù),這意味著我們可以在函數(shù)內(nèi)聲明函數(shù)并且所有的作用域和聲明周期規(guī)則也同樣適用。

>>> def outer():
... x = 1
... def inner():
... print x # 1
... inner() # 2
...
>>> outer()
1

這看起來稍顯復(fù)雜,但其行為仍相當(dāng)直接,易于理解??紤]一下在#1處發(fā)生了什么——Python尋找一個(gè)名為x的local變量,失敗了,然后在最鄰近的外層作用域里搜尋,這個(gè)作用域是另一個(gè)函數(shù)!變量x是函數(shù)outer的local變量,但是和前文提到的一樣,inner函數(shù)擁有對外層作用域的訪問權(quán)限(最起碼有讀和修改的權(quán)限)。在#2處我們調(diào)用了inner函數(shù)。請記住inner也只是一個(gè)變量名,它也遵從Python的變量查找規(guī)則——Python首先在outer的作用域里查找之,找到了一個(gè)名為inner的local變量。

7、函數(shù)是一等公民(Functions are first class objects in Python)

在Python中,這是一個(gè)常識,函數(shù)是和其它任何東西一樣的對象。呃,函數(shù)包含變量,它不是那么的特殊!

>>> issubclass(int, object) # all objects in Python inherit from a common baseclass
True
>>> def foo():
... pass
>>> foo.__class__ # 1>>> issubclass(foo.__class__, object)
True

你也許從沒想到過函數(shù)也有屬性,但是在Python中,和其它任何東西一樣,函數(shù)是對象。(如果你發(fā)覺這令你感到困惑,請等一下,知道你了解到在Python中像其它任何東西一樣,class也是對象?。┮苍S正是因?yàn)檫@一點(diǎn)使Python多少有點(diǎn)“學(xué)術(shù)”的意味——在Python中像其它任何值一樣只是常規(guī)的值而已。這意味著你可以將函數(shù)作為參數(shù)傳遞給函數(shù)或者在函數(shù)中將函數(shù)作為返回值返回!如果你從未考慮過這種事情請考慮下如下的合法Python代碼:

>>> def add(x, y):
... return x + y
>>> def sub(x, y):
... return x - y
>>> def apply(func, x, y): # 1
... return func(x, y) # 2
>>> apply(add, 2, 1) # 3
3
>>> apply(sub, 2, 1)
1

這個(gè)例子對你來說可能也不是太奇怪——add和sub是標(biāo)準(zhǔn)的Python函數(shù),它們都接受兩個(gè)值并返回一個(gè)計(jì)算了的結(jié)果。在#1處你可以看到變量接受一個(gè)函數(shù)就像其它任何普通的變量。在#2處我們調(diào)用傳入apply的函數(shù)——在Python里雙括號是調(diào)用操作符,并且調(diào)用變量名包含的值。在#3處你可以看出在Python中將函數(shù)當(dāng)做值進(jìn)行傳遞并沒有任何特殊語法——函數(shù)名就像任何其它變量一樣只是變量標(biāo)簽。

你之前可能見過這種行為——Python將函數(shù)作為參數(shù)經(jīng)常見于像通過為key參數(shù)提供一個(gè)函數(shù)來自定義sorted內(nèi)建函數(shù)等操作中。但是,將函數(shù)作為返回值返回會怎樣呢?請考慮:

>>> def outer():
... def inner():
... print "Inside inner"
... return inner # 1
...
>>> foo = outer() #2
>>> foo # doctest:+ELLIPSIS

>>> foo()
Inside inner

這乍看起來有點(diǎn)奇怪。在#1處我返回了變量inner,它碰巧是一個(gè)函數(shù)標(biāo)簽。這里沒有特殊語法——我們的函數(shù)返回了inner函數(shù)(調(diào)用outer()函數(shù)并不產(chǎn)生可見的執(zhí)行)。還記得變量的生命周期嗎?每當(dāng)outer函數(shù)被調(diào)用時(shí)inner函數(shù)就會重新被定義一次,但是如果inner函數(shù)不被(outer)返回那么當(dāng)超出outer的作用域后,inner將不復(fù)存在了。

在#2處我們可以獲取到返回值,它是我們的inner函數(shù),它被存儲于一個(gè)新的變量foo。我們可以看到,如果我們計(jì)算foo,它真的包含inner函數(shù),我們可以通過使用調(diào)用運(yùn)算符(雙括號,還記得嗎?)來調(diào)用它。這看起來可能有點(diǎn)怪異,但是到目前為止沒有什么難以理解,不是么?挺住,因?yàn)榻酉聛淼臇|西將會很怪異。

8、閉包(Closures)

讓我們不從定義而是從另一個(gè)代碼示例開始。如果我們將上一個(gè)例子稍加修改會怎樣呢?

>>> def outer():
... x = 1
... def inner():
... print x # 1
... return inner
>>> foo = outer()
>>> foo.func_closure # doctest: +ELLIPSIS
(,)

從上一個(gè)例子中我們看到inner是一個(gè)由outer返回的函數(shù),存儲于一個(gè)名為foo的變量,我們可以通過foo()調(diào)用它。但是它能運(yùn)行嗎?讓我們先來考慮一下作用域規(guī)則。

一切都依照Python的作用域規(guī)則而運(yùn)行——x是outer函數(shù)了一個(gè)local變量。當(dāng)inner在#1處打印x時(shí),Python在inner中尋找一個(gè)local變量,沒有找到;然后它在外層作用域即outer函數(shù)中尋找并找到了它。

但是自此處從變量生命周期的角度來看又會如何呢?變量x是函數(shù)outer的local變量,這意味著只有當(dāng)outer函數(shù)運(yùn)行時(shí)它才存在。只有當(dāng)outer返回后我們才能調(diào)用inner,因此依照我們關(guān)于Python如何運(yùn)作的模型來看,在我們調(diào)用inner的時(shí)候x已經(jīng)不復(fù)存在了,那么某個(gè)運(yùn)行時(shí)錯(cuò)誤可能會出現(xiàn)。

事實(shí)與我們的預(yù)想并不一致,返回的inner函數(shù)的確正常運(yùn)行。Python支持一種稱為閉包(function closures)的特性,這意味著定義于非全局作用域的inner函數(shù)在定義時(shí)記得它們的外層作用域長什么樣。這可以通過查看inner函數(shù)的func_closure屬性來查看,它包含了外層作用域里的變量。

請記住,每次當(dāng)outer函數(shù)被調(diào)用時(shí)inner函數(shù)都被重新定義一次。目前x的值沒有改變,因此我們得到的每個(gè)inner函數(shù)和其它的inner函數(shù)擁有相同的行為,但是如果我們將它做出一點(diǎn)改變呢?

>>> def outer(x):
... def inner():
... print x # 1
... return inner
>>> print1 = outer(1)
>>> print2 = outer(2)
>>> print1()
1
>>> print2()
2

從這個(gè)例子中你可以看到closures——函數(shù)記住他們的外層作用域的事實(shí)——可以用來構(gòu)建本質(zhì)上有一個(gè)硬編碼參數(shù)的自定義函數(shù)。我們沒有將數(shù)字1或者2傳遞給我們的inner函數(shù)但是構(gòu)建了能"記住"其應(yīng)該打印數(shù)字的自定義版本。

closures就是一個(gè)強(qiáng)有力的技術(shù)——你甚至想到在某些方面它有點(diǎn)類似于面向?qū)ο蠹夹g(shù):outer是inner的構(gòu)造函數(shù),x扮演著一個(gè)類似私有成員變量的角色。它的作用有很多,如果你熟悉Python的sorted函數(shù)的key參數(shù),你可能已經(jīng)寫過一個(gè)lambda函數(shù)通過第二項(xiàng)而不是第一項(xiàng)來排序一些列l(wèi)ist。也許你現(xiàn)在可以寫一個(gè)itemgetter函數(shù),它接收一個(gè)用于檢索的索引并返回一個(gè)函數(shù),這個(gè)函數(shù)適合傳遞給key參數(shù)。

但是讓我們不要用閉包做任何噩夢般的事情!相反,讓我們重新從頭開始來寫一個(gè)decorator!

9、裝飾器(Decorators)

一個(gè)decorator只是一個(gè)帶有一個(gè)函數(shù)作為參數(shù)并返回一個(gè)替換函數(shù)的閉包。我們將從簡單的開始一直到寫出有用的decorators。

>>> def outer(some_func):
... def inner():
... print "before some_func"
... ret = some_func() # 1
... return ret + 1
... return inner
>>> def foo():
... return 1
>>> decorated = outer(foo) # 2
>>> decorated()
before some_func
2

請仔細(xì)看我們的decorator實(shí)例。我們定義了一個(gè)接受單個(gè)參數(shù)some_func的名為outer的函數(shù)。在outer內(nèi)部我們定義了一個(gè)名為inner的嵌套函數(shù)。inner函數(shù)打印一個(gè)字符串然后調(diào)用some_func,在#1處緩存它的返回值。some_func的值可能在每次outer被調(diào)用時(shí)不同,但是無論它是什么我們都將調(diào)用它。最終,inner返回some_func的返回值加1,并且我們可以看到,當(dāng)我們調(diào)用存儲于#2處decorated里的返回函數(shù)時(shí)我們得到了輸出的文本和一個(gè)返回值2而不是我們期望的調(diào)用foo產(chǎn)生的原始值1.

我們可以說decorated變量是foo的一個(gè)“裝飾”版本——由foo加上一些東西構(gòu)成。實(shí)際上,如果我們寫了一個(gè)有用的decorator,我們可能想用裝飾后的版本來替換foo,從而可以得到foo的“增添某些東西”的版本。我們可以不用學(xué)習(xí)任何新語法而做到這一點(diǎn)——重新將包含我們函數(shù)的變量進(jìn)行賦值:

>>> foo = outer(foo)
>>> foo # doctest: +ELLIPSIS

現(xiàn)在任何對foo()的調(diào)用都不會得到原始的foo,而是會得到我們經(jīng)過裝飾的版本!領(lǐng)悟到了一些decorator的思想嗎?

10、裝飾器的語法糖--@符號(The @ symbol applies a decorator to a function)

Python 2.4通過在函數(shù)定義前添加一個(gè)@符號實(shí)現(xiàn)對函數(shù)的包裝。在上面的代碼示例中,我們用一個(gè)包裝了的函數(shù)來替換包含函數(shù)的變量來實(shí)現(xiàn)了包裝。

>>> add = wrapper(add)

這一模式任何時(shí)候都可以用來包裝任何函數(shù),但是如果們定義了一個(gè)函數(shù),我們可以用@符號像下面示例那樣包裝它:

>>> @wrapper
... def add(a, b):
... return Coordinate(a.x + b.x, a.y + b.y)

請注意,這種方式和用wrapper函數(shù)的返回值來替換原始變量并沒有任何不同,Python只是增添了一些語法糖(syntactic sugar)讓它看起來更明顯一點(diǎn)。

11、*args and **kwargs

我們已經(jīng)寫了一個(gè)有用的decorator,但是它是硬編碼的,它只適用于特定種類的函數(shù)——帶有兩個(gè)參數(shù)的函數(shù)。我們函數(shù)內(nèi)部的checker函數(shù)接受了兩個(gè)參數(shù),然后繼續(xù)將參數(shù)閉包里的函數(shù)。如果我們想要一個(gè)能包裝任何類型函數(shù)的decorator呢?讓我們實(shí)現(xiàn)一個(gè)在不改變被包裝函數(shù)的前提下對每一次被包裝函數(shù)的調(diào)用增添一次計(jì)數(shù)的包裝器。這意味著這個(gè)decorator需要接受所有待包裝的任何函數(shù)并將傳遞給它的任何參數(shù)傳遞給被包裝的函數(shù)來調(diào)用它(被包裝的函數(shù))。

這種情況很常見,所以Python為這一特性提供了語法支持。請確保閱讀Python Tutorial以了解更多,但是在函數(shù)定義時(shí)使用*運(yùn)算符意味著任何傳遞給函數(shù)的額外位置參數(shù)最終以一個(gè)*作為前導(dǎo)。因此:

>>> def one(*args):
... print args # 1
>>> one()
()
>>> one(1, 2, 3)
(1, 2, 3)
>>> def two(x, y, *args): # 2
... print x, y, args
>>> two('a', 'b', 'c')
a b ('c')

第一個(gè)函數(shù)one只是簡單的將任何(如果有)傳遞給它的位置參數(shù)打印出來。正如你在#1處見到的,在函數(shù)內(nèi)部我們只是引用了args變量——*args只是表明在函數(shù)定義中位置參數(shù)應(yīng)該保存在變量args中。Python也允許我們指定一些變量并捕獲到任何在args變量里的其它參數(shù),正如#2處所示。

*運(yùn)算符也可以用于函數(shù)調(diào)用中,這時(shí)它也有著類似的意義。在調(diào)用一個(gè)函數(shù)時(shí)帶有一個(gè)以*為前導(dǎo)的變量作為參數(shù)表示這個(gè)變量內(nèi)容需要被解析然后用作位置參數(shù)。再一次以實(shí)例來說明:

>>> def add(x, y):
... return x + y
>>> lst = [1, 2]
>>> add(lst[0], lst[1]) # 1
3
>>> add(*lst) # 2
3

#1處的代碼抽取出了和#2處相同的參數(shù)——在#2處Python為我們自動解析了參數(shù),我們也可以像在#1處一樣自己解析出來。這看起來不錯(cuò),*args既表示當(dāng)調(diào)用函數(shù)是從一個(gè)iterable抽取位置參數(shù),也表示當(dāng)定義一個(gè)函數(shù)是接受任何額外的位置變量。

當(dāng)我們引入**時(shí),事情變得更加復(fù)雜點(diǎn),與*表示iterables和位置參數(shù)一樣,**表示dictionaries & key/value對。很簡單,不是么?

>>> def foo(**kwargs):
... print kwargs
>>> foo()
{}
>>> foo(x=1, y=2)
{'y': 2, 'x': 1}

當(dāng)我們定義一個(gè)函數(shù)時(shí)我們可以用**kwargs表明所有未捕獲的keyword變量應(yīng)該被存儲在一個(gè)名為kwargs的字典中。前面的例子中的args和本例中的kwargs都不是Python語法的一部分,但是在函數(shù)定義時(shí)使用這兩個(gè)作為變量名時(shí)一種慣例。就像*一樣,我們可以在函數(shù)調(diào)用時(shí)使用**。

>>> dct = {'x': 1, 'y': 2}
>>> def bar(x, y):
... rturn x + y
>>> bar(**dct)
3

12、更通用的裝飾器(More generic decorators)

用我們掌握的新“武器”我們可以寫一個(gè)decorator用來“記錄”函數(shù)的參數(shù)。為了簡單起見,我們將其打印在stdout上:

>>> def logger(func):
... def inner(*args, **kwargs): # 1
... print "Arguments were: %s, %s" % (args, kwargs)
... return func(*args, **kwargs) # 2
... return inner

注意到在#1處inner函數(shù)帶有任意數(shù)量的任何類型的參數(shù),然后在#2處將它們傳遞到被包裝的函數(shù)中。這允許我們包裝或者裝飾任何函數(shù)。

>>> @logger
... def foo1(x, y=1):
... return x * y
>>> @logger
... def foo2():
... return 2
>>> foo1(5, 4)
Arguments were: (5, 4), {}
20
>>> foo1(1)
Arguments were: (1,), {}
1
>>> foo2()
Arguments were: (),{}
2

對函數(shù)的調(diào)用會產(chǎn)生一個(gè)"logging"輸出行,也會輸出一個(gè)如我們期望的函數(shù)返回值。

到此,關(guān)于“怎么理解Python裝飾器”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!


文章標(biāo)題:怎么理解Python裝飾器-創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://weahome.cn/article/cscejh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部