http://blog.csdn.net/ablo_zhou/article/details/5471952
Python 2.4以后,增加了@符號修飾函數(shù)對函數(shù)進(jìn)行修飾,python3.0/2.6又增加了對類的修飾。
我現(xiàn)在使用的python版本,支持對class的修飾:
zhouhh@zhouhh-home:~$ python
Python 2.6.4 (r264:75706, Dec? 7 2009, 18:45:15)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
@修飾符挺像是處理函數(shù)或類之前進(jìn)行預(yù)處理。
語法示例:
@dec1
@dec2
def test(arg):
? ? pass
其效果類似于
dec1(dec2(test(arg)))
修飾函數(shù)還可以帶參數(shù)。
@dec1(arg1,arg2)
def test(testarg)
效果類似于
dec1(arg1,arg2)(test(arg))
[]
http://blog.csdn.net/guang11cheng/article/details/51179410
示例1
def minus(f):
? ? print 'minus'
? ? f()
def plus(f):
? ? print 'plus'
? ? f()
def test(a):
? ? if a > 3 :
? ? ? ? return plus
? ? else :
? ? ? ? return minus
@test(5)
def xxx():
? ? print 'ok'
解釋器首先會解釋@符號后面的代碼,如果如上面的代碼類似,那么test(5)將被執(zhí)行,因?yàn)閠est參數(shù)5大于3,所以會返回函數(shù)指針plus(可以用C的這個(gè)名字來理解),plus將下一行的函數(shù)指針xxx當(dāng)作參數(shù)傳入,直到執(zhí)行完成。最后結(jié)果將輸出‘plus’和‘ok’。 有時(shí)候可能是下面這種形式:
示例2
def minus(f):
? ? print 'minus'
? ? f()
@minus
def xxx():
? ? print 'ok'
minus因?yàn)楸旧硪呀?jīng)是一個(gè)函數(shù)指針,所以會直接以xxx作為參數(shù)傳入,結(jié)果會輸出‘minus’和‘ok’。
--wjt:是不是說,如果一個(gè)函數(shù)的入?yún)⑹橇硪粋€(gè)函數(shù)(實(shí)例2),或者一個(gè)函數(shù)的返回值是另一個(gè)帶函數(shù)參數(shù)的函數(shù)(實(shí)例1),那么這個(gè)函數(shù)就可以被@。?
即被@的函數(shù),其需要有能力接收的起下一行的函數(shù)進(jìn)入自己的函數(shù)體中。?
果真如此。那么裝飾器其實(shí)并沒有什么神秘的,無非就是一個(gè)語法:
語法示例:
@dec1
@dec2
def test(arg):
? ? pass
其效果類似于
dec1(dec2(test(arg)))
只需要遵守其語法。實(shí)質(zhì)按上面藍(lán)色字體講的理解即可。
即裝飾器:(1)形式上要求即被@的函數(shù),其需要有能力接收的起下一行的函數(shù)進(jìn)入自己的函數(shù)體中;(2)實(shí)質(zhì)執(zhí)行上效果類似于dec1(dec2(test(arg)))。
下面的例子我分析出的結(jié)果正確,說明我的理解到位:
def f1(arg):
? ? print "f1"
? ? rl = arg()
? ? print rl
? ? return rl + "f1"
@f1
def f2(s = ""):
? ? print "f2"
? ? return s + "f2r"
print "start"
D:\Users\wangjiangtao517>python D:\wangjt\zsq.py
f1
f2
f2r
start
--------------------------------------------------------------------
《一步一步詳解裝飾器》
http://python.jobbole.com/81683/
6. 嵌套函數(shù)
Python允許創(chuàng)建嵌套函數(shù)。這意味著我們可以在函數(shù)里面定義函數(shù)而且現(xiàn)有的作用域和變量生存周期依舊適用。
def outer():
? ? x = 1
? ? def inner():
? ? ? ? print x # 1
? ? inner() # 2
outer()
1
這個(gè)例子有一點(diǎn)兒復(fù)雜,但是看起來也還行。想一想在#1發(fā)生了什么:python解釋器需找一個(gè)叫x的本地變量,查找失敗之后會繼續(xù)在上層的作用域里面尋找,這個(gè)上層的作用域定義在另外一個(gè)函數(shù)里面。對函數(shù)outer來說,變量x是一個(gè)本地變量,但是如先前提到的一樣,函數(shù)inner可以訪問封閉的作用域(至少可以讀和修改)。在#2處,我們調(diào)用函數(shù)inner,非常重要的一點(diǎn)是,inner也僅僅是一個(gè)遵循python變量解析規(guī)則的變量名,python解釋器會優(yōu)先在outer的作用域里面對變量名inner查找匹配的變量.
7. 函數(shù)是python世界里的一級類對象
顯而易見,在python里函數(shù)和其他東西一樣都是對象。
issubclass(int, object) # all objects in Python inherit from a common baseclass
True
def foo():
? ? pass
foo.__class__ # 1
<type 'function'>
issubclass(foo.__class__, object)
True
函數(shù)在python里面就是對象,和其他的東西一樣,也許這樣描述會太學(xué)院派太官方了點(diǎn):在python里,函數(shù)只是一些普通的值而已和其他的值一毛一樣。這就是說你可以把函數(shù)像參數(shù)一樣傳遞給其他的函數(shù)或者說從函數(shù)了里面返回函數(shù)!如果你從來沒有這么想過,那看看下面這個(gè)例子:
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
把函數(shù)當(dāng)做返回值:
def outer():
? ? def inner():
? ? ? ? print "Inside inner"
? ? return inner # 1
foo = outer() #2
>>> foo
<function inner at 0x03912DF0> --- 顯示變量 foo 的值(是一個(gè)函數(shù))
>>> foo()
Inside inner? ---執(zhí)行了函數(shù)inner()
這個(gè)例子看起來也許會更加的奇怪。在#1處我把恰好是函數(shù)標(biāo)識符的變量inner作為返回值返回出來。這并沒有什么特殊的語法:”把函數(shù)inner返回出來,否則它根本不可能會被外界所調(diào)用?!斑€記得變量的生存周期嗎?每次函數(shù)outer被調(diào)用的時(shí)候,函數(shù)inner都會被重新定義,如果它不被當(dāng)做變量返回的話,每次執(zhí)行過后它將不復(fù)存在。
在#2處我們捕獲返回值 – 函數(shù)inner,將它存在一個(gè)新的變量foo里。我們能夠看到,當(dāng)對變量foo進(jìn)行求值,它確實(shí)包含函數(shù)inner,而且我們能夠?qū)λM(jìn)行調(diào)用。初次看起來可能會覺得有點(diǎn)奇怪,但是理解起來并不困難是吧。
8. 閉包
def outer(x):
? ? def inner():
? ? ? ? print x # 1
? ? return inner
print1 = outer(1)
print2 = outer(2)
print1()
1
print2()
2
9. 裝飾器
裝飾器其實(shí)就是一個(gè)閉包,把一個(gè)函數(shù)當(dāng)做參數(shù)然后返回一個(gè)替代版函數(shù).
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ì)看看上面這個(gè)裝飾器的例子。我們定義了一個(gè)函數(shù)outer,它只有一個(gè)some_func的參數(shù),在他里面我們定義了一個(gè)嵌套的函數(shù)inner。inner會打印一串字符串,然后調(diào)用some_func,在#1處得到它的返回值。在outer每次調(diào)用的時(shí)候some_func的值可能會不一樣,但是不管some_func的之如何,我們都會調(diào)用它。最后,inner返回some_func() + 1的值 – 我們通過調(diào)用在#2處存儲在變量decorated里面的函數(shù)能夠看到被打印出來的字符串以及返回值2。
我們可以認(rèn)為變量decorated是函數(shù)foo的一個(gè)裝飾版本,一個(gè)加強(qiáng)版本。事實(shí)上如果打算寫一個(gè)有用的裝飾器的話,我們可能會想愿意用裝飾版本完全取代原先的函數(shù)foo,這樣我們總是會得到我們的”加強(qiáng)版“foo。想要達(dá)到這個(gè)效果,完全不需要學(xué)習(xí)新的語法,簡單地賦值給變量foo就行了:
foo = outer(foo)
foo # doctest: +ELLIPSIS
<function inner at 0x>
現(xiàn)在,任何怎么調(diào)用都不會牽扯到原先的函數(shù)foo,都會得到新的裝飾版本的foo
--------------------------------
《closure(閉包)》
https://www.cnblogs.com/Pierre-de-Ronsard/archive/2012/08/20/2647812.html
closure概念:在一個(gè)內(nèi)部函數(shù)中,對外部作用域的變量進(jìn)行引用,那么內(nèi)部函數(shù)就被認(rèn)為是closure(閉包)
自由變量:定義在外部函數(shù)內(nèi),被內(nèi)部函數(shù)引用或者使用的變量為自由變量
函數(shù)func_closure 在函數(shù)被調(diào)用前和調(diào)用后使用,效果是一樣的
https://segmentfault.com/a/1190000007321972
用比較容易懂的人話說,就是當(dāng)某個(gè)函數(shù)被當(dāng)成對象返回時(shí),夾帶了外部變量,就形成了一個(gè)閉包??蠢?。
def make_printer(msg):
? ? def printer():
? ? ? ? print msg? # 夾帶私貨(外部變量)
? ? return printer? # 返回的是函數(shù),帶私貨的函數(shù)
printer = make_printer('Foo!')
printer()
支持將函數(shù)當(dāng)成對象使用的編程語言,一般都支持閉包。比如Python, JavaScript。
我個(gè)人認(rèn)為,閉包存在的意義就是它夾帶了外部變量(私貨),如果它不夾帶私貨,它和普通的函數(shù)就沒有任何區(qū)別。同一個(gè)的函數(shù)夾帶了不同的私貨,就實(shí)現(xiàn)了不同的功能。其實(shí)你也可以這么理解,閉包和面向接口編程的概念很像,可以把閉包理解成輕量級的接口封裝。
ef tag(tag_name):
? ? def add_tag(content):
? ? ? ? return "<{0}>{1}</{0}>".format(tag_name, content)
? ? return add_tag
content = 'Hello'
add_tag = tag('a')
print add_tag(content)
# <a>Hello</a>
add_tag = tag('b')
print add_tag(content)
# <b>Hello</b>
在這個(gè)例子里,我們想要一個(gè)給content加tag的功能,但是具體的tag_name是什么樣子的要根據(jù)實(shí)際需求來定,對外部調(diào)用的接口已經(jīng)確定,就是add_tag(content)。如果按照面向接口方式實(shí)現(xiàn),我們會先把a(bǔ)dd_tag寫成接口,指定其參數(shù)和返回類型,然后分別去實(shí)現(xiàn)a和b的add_tag。
但是在閉包的概念中,add_tag就是一個(gè)函數(shù),它需要tag_name和content兩個(gè)參數(shù),只不過tag_name這個(gè)參數(shù)是打包帶走的。所以一開始時(shí)就可以告訴我怎么打包,然后帶走就行。
--------------------
《format函數(shù)》
https://www.cnblogs.com/chunlaipiupiupiu/p/7978669.html
python中format函數(shù)用于字符串的格式化
通過關(guān)鍵字
1 print('{名字}今天{動作}'.format(名字='陳某某',動作='拍視頻'))#通過關(guān)鍵字
2 grade = {'name' : '陳某某', 'fenshu': '59'}
3 print('{name}電工考了{(lán)fenshu}'.format(**grade))#通過關(guān)鍵字,可用字典當(dāng)關(guān)鍵字傳入值時(shí),在字典前加**即可
通過位置
1 print('{1}今天{0}'.format('拍視頻','陳某某'))#通過位置
2 print('{0}今天{1}'.format('陳某某','拍視頻'))
填充和對齊^<>分別表示居中、左對齊、右對齊,后面帶寬度
1 print('{:^14}'.format('陳某某'))
2 print('{:>14}'.format('陳某某'))
3 print('{:<14}'.format('陳某某'))
4 print('{:*<14}'.format('陳某某'))
5 print('{:&>14}'.format('陳某某'))#填充和對齊^<>分別表示居中、左對齊、右對齊,后面帶寬度
精度和類型f精度常和f一起使用
1 print('{:.1f}'.format(4.234324525254))
2 print('{:.4f}'.format(4.1))
進(jìn)制轉(zhuǎn)化,b o d x 分別表示二、八、十、十六進(jìn)制
print('{:b}'.format(250))
print('{:o}'.format(250))
print('{:d}'.format(250))
print('{:x}'.format(250))
千分位分隔符,這種情況只針對與數(shù)字
print('{:,}'.format(100000000))
print('{:,}'.format(235445.234235))
--------------------
《案例》
[]
http://blog.sina.com.cn/s/blog_6fe87f870101d9cm.html
'@'符號用作函數(shù)修飾符必須出現(xiàn)在函數(shù)定義前一行,不允許和函數(shù)定義在同一行。也就是說@A def f(): 是非法的。 只可以在模塊或類定義層內(nèi)對函數(shù)進(jìn)行修飾。一個(gè)修飾符就是一個(gè)函數(shù),它將被修飾的函數(shù)做為參數(shù),并返回修飾后的同名函數(shù)或其它可調(diào)用的東西。
下面不懂:
###################################
def spamrun(fn):
? ? def sayspam(*args):
? ? ? ? print "spam,spam,spam"
? ? return sayspam
@spamrun
def useful(a,b):
? ? print a**2+b**2
useful(3,4)
###################################
D:\Users\wangjiangtao517>python D:\wangjt\zsq.py
spam,spam,spam
###################################
def spamrun(fn):
? ? def sayspam(*args):
? ? ? ? print "spam,spam,spam"
? ? return sayspam
#@spamrun
def useful(a,b):
? ? print a**2+b**2
useful(3,4)
###################################
D:\Users\wangjiangtao517>python D:\wangjt\zsq.py
25
###################################
def spamrun(fn):
? ? def sayspam(*args):
? ? ? ? print "spam,spam,spam"
? ? #return sayspam
#@spamrun
def useful(a,b):
? ? print a**2+b**2
useful(3,4)
###################################
D:\Users\wangjiangtao517>python D:\wangjt\zsq.py
Traceback (most recent call last):
? File "D:\wangjt\zsq.py", line 10, in <module>
? ? useful(3,4)
TypeError: 'NoneType' object is not callable
實(shí)例
def decorator(fn):
? ? def test(*args):
? ? ? ? print "My god!"*3
? ? ? ? return fn(*args)
? ? return test
@decorator
def other(a,b):
? ? print a**2+b**2
if __name__=="__main__":
? ? other(4,3)
? ? other(3,4)
結(jié)果:
My god!My god!My god!
25
My god!My god!My god!
25
注釋掉//print return fn(*args)
結(jié)果是:
My god!My god!My god!
My god!My god!My god!
要想使other函數(shù)能正常運(yùn)行,必須加返回值,@decorator是一個(gè)statement,會將other函數(shù)當(dāng)作參數(shù)傳入來執(zhí)行test方法
------------------
《主線程、子線程主線程、子線程》
用裝飾器實(shí)現(xiàn)子線程執(zhí)行10分鐘還沒返回被主線程kill掉?