python函數(shù)復(fù)用代碼 python函數(shù)與代碼復(fù)用的例題

python協(xié)程和異步IO——IO多路復(fù)用

C10k是一個(gè)在1999年被提出來(lái)的技術(shù)挑戰(zhàn),如何在一顆1GHz CPU,2G內(nèi)存,1gbps網(wǎng)絡(luò)環(huán)境下,讓單臺(tái)服務(wù)器同時(shí)為1萬(wàn)個(gè)客戶端提供FTP服務(wù)

創(chuàng)新互聯(lián)專注于輝縣網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供輝縣營(yíng)銷型網(wǎng)站建設(shè),輝縣網(wǎng)站制作、輝縣網(wǎng)頁(yè)設(shè)計(jì)、輝縣網(wǎng)站官網(wǎng)定制、小程序制作服務(wù),打造輝縣網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供輝縣網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。

阻塞式I/O(使用最多)、非阻塞式I/O、I/O復(fù)用、信號(hào)驅(qū)動(dòng)式I/O(幾乎不使用)、異步I/O(POSIX的aio_系列函數(shù))

select、poll、epoll都是IO多路復(fù)用的機(jī)制。I/O多路復(fù)用就是通過(guò)一種機(jī)制,一個(gè)進(jìn)程可以監(jiān)聽(tīng)多個(gè)描述符,一旦,某個(gè)描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進(jìn)行相應(yīng)的讀寫操作。但select、poll、epoll本質(zhì)上都是同步I/O,因?yàn)樗麄兌夹枰谧x寫時(shí)間就緒后負(fù)責(zé)進(jìn)行讀寫,也就是說(shuō)讀寫過(guò)程是阻塞的,而異步I/O無(wú)需自己負(fù)責(zé)進(jìn)行讀寫,異步I/O的實(shí)現(xiàn)會(huì)負(fù)責(zé)把數(shù)據(jù)從內(nèi)核拷貝到用戶空間

(1)select

select函數(shù)監(jiān)視的文件描述符分3類,分別是writefds、readfds、exceptfds。調(diào)用select函數(shù)會(huì)阻塞,直到有描述符就緒(有數(shù)據(jù)可讀、可寫或者有except),或者超時(shí)函數(shù)返回。當(dāng)select函數(shù)返回后可以通過(guò)遍歷fdset來(lái)找到就緒的描述符。

select目前幾乎在所有的平臺(tái)上支持,其良好的跨平臺(tái)支持也是它的一個(gè)優(yōu)點(diǎn)。select的一個(gè)缺點(diǎn)在于單個(gè)進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,在Linux上一般為1024,可以通過(guò)修改宏定義甚至重新編譯內(nèi)核的方式提升這一限制,但是這樣也會(huì)降低效率。

(2)poll

不同于select使用三個(gè)位圖來(lái)表示三個(gè)fdset的方式,poll使用一個(gè)pollfd的指針實(shí)現(xiàn)。

pollfd結(jié)構(gòu)包含了要監(jiān)視的event和發(fā)生的event,不再使用select"參數(shù)-值"傳遞的方式。同時(shí)pollfd并沒(méi)有最大數(shù)量限制(但是數(shù)量過(guò)大后性能也會(huì)下降)。和select函數(shù)一樣,poll返回后,需要輪詢pollfd來(lái)獲取就緒的描述符。

從上面看,select和poll都需要在返回后通過(guò)遍歷文件描述符來(lái)獲取已經(jīng)就緒的socket。事實(shí)上同時(shí)連接的大量客戶端在同一時(shí)刻可能只有很少的處于就緒的狀態(tài),因此隨著監(jiān)視的描述符數(shù)量的增長(zhǎng),其效率也會(huì)線性下降

(3)epoll

epoll是在2.6內(nèi)核中提出的,是之前的select和poll的增強(qiáng)版本。相對(duì)于select和poll來(lái)說(shuō),epoll更加領(lǐng)靈活,沒(méi)有描述符限制。epoll使用一個(gè)文件描述符管理多個(gè)描述符,將用戶關(guān)系的文件描述符的事件存放到內(nèi)核的一個(gè)事件表中,這樣在用戶空間和內(nèi)核空間的copy只需一次。

Python編程題怎么寫?

Python編程題寫法:第一個(gè)問(wèn)題使用排序算法,有很多種,可以使用簡(jiǎn)單一點(diǎn)的冒泡排序。第二個(gè)問(wèn)題為了確保是輸入了5個(gè)整數(shù),可以使用while循環(huán)+try。

假設(shè)data.txt中所有的號(hào)碼都在一行,沒(méi)有換行,寫入到data_asc.txt中時(shí),假設(shè)每行一個(gè),原文件中是否有換行;寫入到data_asc.txt文件中時(shí),是一行一個(gè);還是所有的都在一行,然后用英文逗號(hào)隔開。

Python

是完全面向?qū)ο蟮恼Z(yǔ)言。函數(shù)、模塊、數(shù)字、字符串都是對(duì)象。并且完全支持繼承、重載、派生、多繼承,有益于增強(qiáng)源代碼的復(fù)用性。Python支持重載運(yùn)算符和動(dòng)態(tài)類型。相對(duì)于Lisp這種傳統(tǒng)的函數(shù)式編程語(yǔ)言,Python對(duì)函數(shù)式設(shè)計(jì)只提供了有限的支持。有兩個(gè)標(biāo)準(zhǔn)庫(kù)(functools, itertools)提供了Haskell和Standard ML中久經(jīng)考驗(yàn)的函數(shù)式程序設(shè)計(jì)工具。

如何理解 Python

先來(lái)看一個(gè)簡(jiǎn)單例子:

def foo():

print('i am foo')

現(xiàn)在有一個(gè)新的需求,希望可以記錄下函數(shù)的執(zhí)行日志,于是在代碼中添加日志代碼:

def foo():

print('i am foo')

logging.info("foo is running")

bar()、bar2()也有類似的需求,怎么做?再寫一個(gè)logging在bar函數(shù)里?這樣就造成大量雷同的代碼,為了減少重復(fù)寫代碼,我們可以這樣做,重新定義一個(gè)函數(shù):專門處理日志 ,日志處理完之后再執(zhí)行真正的業(yè)務(wù)代碼

def use_logging(func):

logging.warn("%s is running" % func.__name__)

func()

def bar():

print('i am bar')

use_logging(bar)

邏輯上不難理解, 但是這樣的話,我們每次都要將一個(gè)函數(shù)作為參數(shù)傳遞給use_logging函數(shù)。而且這種方式已經(jīng)破壞了原有的代碼邏輯結(jié)構(gòu),之前執(zhí)行業(yè)務(wù)邏輯時(shí),執(zhí)行運(yùn)行bar(),但是現(xiàn)在不得不改成use_logging(bar)。那么有沒(méi)有更好的方式的呢?當(dāng)然有,答案就是裝飾器。

簡(jiǎn)單裝飾器

def use_logging(func):

def wrapper(*args, **kwargs):

logging.warn("%s is running" % func.__name__)

return func(*args, **kwargs)

return wrapper

def bar():

print('i am bar')

bar = use_logging(bar)

bar()

函數(shù)use_logging就是裝飾器,它把執(zhí)行真正業(yè)務(wù)方法的func包裹在函數(shù)里面,看起來(lái)像bar被use_logging裝飾了。在這個(gè)例子中,函數(shù)進(jìn)入和退出時(shí) ,被稱為一個(gè)橫切面(Aspect),這種編程方式被稱為面向切面的編程(Aspect-Oriented Programming)。

@符號(hào)是裝飾器的語(yǔ)法糖,在定義函數(shù)的時(shí)候使用,避免再一次賦值操作

def use_logging(func):

def wrapper(*args, **kwargs):

logging.warn("%s is running" % func.__name__)

return func(*args)

return wrapper

@use_logging

def foo():

print("i am foo")

@use_logging

def bar():

print("i am bar")

bar()

如上所示,這樣我們就可以省去bar = use_logging(bar)這一句了,直接調(diào)用bar()即可得到想要的結(jié)果。如果我們有其他的類似函數(shù),我們可以繼續(xù)調(diào)用裝飾器來(lái)修飾函數(shù),而不用重復(fù)修改函數(shù)或者增加新的封裝。這樣,我們就提高了程序的可重復(fù)利用性,并增加了程序的可讀性。

裝飾器在Python使用如此方便都要?dú)w因于Python的函數(shù)能像普通的對(duì)象一樣能作為參數(shù)傳遞給其他函數(shù),可以被賦值給其他變量,可以作為返回值,可以被定義在另外一個(gè)函數(shù)內(nèi)。

帶參數(shù)的裝飾器

裝飾器還有更大的靈活性,例如帶參數(shù)的裝飾器:在上面的裝飾器調(diào)用中,比如@use_logging,該裝飾器唯一的參數(shù)就是執(zhí)行業(yè)務(wù)的函數(shù)。裝飾器的語(yǔ)法允許我們?cè)谡{(diào)用時(shí),提供其它參數(shù),比如@decorator(a)。這樣,就為裝飾器的編寫和使用提供了更大的靈活性。

def use_logging(level):

def decorator(func):

def wrapper(*args, **kwargs):

if level == "warn":

logging.warn("%s is running" % func.__name__)

return func(*args)

return wrapper

return decorator

@use_logging(level="warn")

def foo(name='foo'):

print("i am %s" % name)

foo()

上面的use_logging是允許帶參數(shù)的裝飾器。它實(shí)際上是對(duì)原有裝飾器的一個(gè)函數(shù)封裝,并返回一個(gè)裝飾器。我們可以將它理解為一個(gè)含有參數(shù)的閉包。當(dāng)我 們使用@use_logging(level="warn")調(diào)用的時(shí)候,Python能夠發(fā)現(xiàn)這一層的封裝,并把參數(shù)傳遞到裝飾器的環(huán)境中。

類裝飾器

再來(lái)看看類裝飾器,相比函數(shù)裝飾器,類裝飾器具有靈活度大、高內(nèi)聚、封裝性等優(yōu)點(diǎn)。使用類裝飾器還可以依靠類內(nèi)部的\_\_call\_\_方法,當(dāng)使用 @ 形式將裝飾器附加到函數(shù)上時(shí),就會(huì)調(diào)用此方法。

class Foo(object):

def __init__(self, func):

self._func = func

def __call__(self):

print ('class decorator runing')

self._func()

print ('class decorator ending')

@Foo

def bar():

print ('bar')

bar()

functools.wraps

使用裝飾器極大地復(fù)用了代碼,但是他有一個(gè)缺點(diǎn)就是原函數(shù)的元信息不見(jiàn)了,比如函數(shù)的docstring、__name__、參數(shù)列表,先看例子:

裝飾器

def logged(func):

def with_logging(*args, **kwargs):

print func.__name__ + " was called"

return func(*args, **kwargs)

return with_logging

函數(shù)

@logged

def f(x):

"""does some math"""

return x + x * x

該函數(shù)完成等價(jià)于:

def f(x):

"""does some math"""

return x + x * x

f = logged(f)

不難發(fā)現(xiàn),函數(shù)f被with_logging取代了,當(dāng)然它的docstring,__name__就是變成了with_logging函數(shù)的信息了。

print f.__name__ # prints 'with_logging'

print f.__doc__ # prints None

這個(gè)問(wèn)題就比較嚴(yán)重的,好在我們有functools.wraps,wraps本身也是一個(gè)裝飾器,它能把原函數(shù)的元信息拷貝到裝飾器函數(shù)中,這使得裝飾器函數(shù)也有和原函數(shù)一樣的元信息了。

from functools import wraps

def logged(func):

@wraps(func)

def with_logging(*args, **kwargs):

print func.__name__ + " was called"

return func(*args, **kwargs)

return with_logging

@logged

def f(x):

"""does some math"""

return x + x * x

print f.__name__ # prints 'f'

print f.__doc__ # prints 'does some math'

內(nèi)置裝飾器

@staticmathod、@classmethod、@property

裝飾器的順序

@a

@b

@c

def f ():

等效于

f = a(b(c(f)))

當(dāng)前標(biāo)題:python函數(shù)復(fù)用代碼 python函數(shù)與代碼復(fù)用的例題
文章來(lái)源:http://www.muchs.cn/article8/docsgop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、全網(wǎng)營(yíng)銷推廣網(wǎng)頁(yè)設(shè)計(jì)公司、響應(yīng)式網(wǎng)站、用戶體驗(yàn)App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)