寫出pythonic的python代碼


http://www.cnblogs.com/dadadechengzi/p/6226071.html

 

1,列表推導(沒當要對序列中的內容進行循環處理時,就應該嘗試使用列表推倒)

  在python中編寫如下的代碼是讓人痛苦和不高效已經簡潔美觀的。

復制代碼
numbers =  range(10)
evens = []
for i in numbers:
    if i % 2 == 0:
        evens.append(i)

print evens
復制代碼

  毫無疑問,在python中它確實會使得程序的執行速度變得慢了(它使解釋程序在每次循環中都要確定序系中哪一部分被修改)

  列表推倒是這種場景下的爭取選擇,它使用編排好的特性對前述語法中的一部分進行了自動化處理:

  events = [i for i in range(10) if i % 2 == 0]

  這種編寫的方法除了高效之外,也更加簡短,涉及的元素也更少。在更大的程序中,這意味着引入的缺陷更少,代碼更加容易閱讀和理解。

2,使用枚舉(enumerate)

  比如下面的代碼就可以換成使用枚舉:

復制代碼
i = 0
seq = ['one','two','three']
for element in seq:
    seq[i] = '%d:%s' % (i,seq[i])
    i += 1

print seq
復制代碼
seq = ['one','two','three']
for index,element in enumrate(seq)
    seq[i] = '%d:%s' % (index,element)

print seq

  也可以結合一個列表推倒將其重構如下:

復制代碼
def _treatment(pos,element):
    return '%d:%s' % (pos,element)

seq = ['one','two','three']
seq = [_treatment(index,ele) for index,ele in enumrate(seq)]

print seq
復制代碼

3,迭代器

  迭代器只不過是一個實現迭代協議的容器對象,它基於兩個方法:

  1. next 返回容器的下一個項目;
  2. __iter__ 返回迭代器本身

  創建定制的迭代器:

復制代碼
class My_Iteration(object):
    def __init__(self,step):
        self.step = step
    
    def next(self):
        if self.step == 0:
            raise StopIteration
        self.step -= 1

    def __iter__(self):
        return self

for i in My_Iteration(5):
    print i
復制代碼

  迭代器本身提供了一個底層的概念,它們為生成器這一更有趣的特性提供了基礎。

4,生成器(當需要一個將返回一個序列或者在循環中執行的函數時就應該考慮使用生成器)

  生成器提供了一個出色的方法,使得需要返回一系列元素的函數所需的代碼更加的簡單、高效。基於yield指令,可以暫停一個函數並返回中間結果。該函數將保存執行環境並在必要的時候恢復。

  生成器對降低程序復雜性也有幫助,並且能夠提升基於多個序列的數據轉換算法的性能。把每個序列當做一個迭代器,然后將他們合並到一個高級別的函數中,這是一種避免函數變得更加龐大,丑陋,不可理解的好辦法,而且,這可以給整個處理鏈提供實時的反饋。

  在下面的例子中,每個函數用來在序列上定義一個轉換,然后他們被鏈接起來應用,每次調用將處理一個元素並返回其結果:

復制代碼
def power(values):
    for value in values:
        print 'power %s' % value
        yield value

def adder(values):
    for value in values:
        print 'adder %s' % value
        if value % 2 == 0:
            yield value + 3
        else:
            yield value + 2

elements = [1,2,3,4,5,7,8]
res = adder(power(elements))

#res 就是一個生成器了
復制代碼

5,裝飾器(decorator)

  裝飾器使得函數和方法封裝(接受一個函數並返回增強版本的一個函數)更加容易閱讀和理解。其實總體說來,裝飾器也就是一個函數,一個用來包裝函數的函數,返回一個修改之后的函數對象,將其重新賦值原來的標示符,並永久喪失對原始函數對象的訪問。

  語法:

  • 無參數裝飾器
復制代碼
def deco(fun):    
    print fun    
    return fun
@deco
def foo():
    pass
foo()
復制代碼

  第一個函數deco是裝飾函數,它的參數就是被裝飾的函數對象,我們可以在deco函數內對傳入的函數對象做一番“裝飾”,然后返回這個對象(一定要返回 ,不然外面調用foo的地方將會無函數可用。實際上此時foo=deco(foo))

  下面有個例子檢查函數有沒有說明文檔:

復制代碼
def deco_functionNeedDoc(func):
    if func.__doc__ == None:
        print func,"has no __doc__,it's a bad habit."
    else:
        print func,":",func.__doc__,"."
    return func

@deco_functionNeedDoc
def f():
    print 'f() has no doc'
#f = deco_functionNeedDoc(f)

@deco_functionNeedDoc
def g():
    'I have a __doc__'
    print 'g() has doc'
#g = deco_functionNeedDoc(g)

f()
g()
復制代碼
  • 有參數裝飾器
復制代碼
def deco_maker(arg):
    '通常對arg會有一定的要求'
    """由於有參數的decorator函數在調用時只會使用應用時的參數而不接收被裝飾的函數做為參數,所以必須在其內部再創建一個函數"""
    
    def newDemo(func):#定義一個新的decorator函數
        print func, arg
        return newDemo
    return newDemo

@deco_maker(deco_args)
def foo():pass

foo()
復制代碼

  第一個函數deco_maker是裝飾函數,它的參數是用來加強“加強裝飾”的。由於此函數並非被裝飾的函數對象,所以在內部必須至少創建一個接受被裝飾函數的函數,然后返回這個對象(實際上此時foo=decomaker(arg)(foo))

  總結:裝飾器可以讓函數輕裝上陣,更重要的是將函數的約束放置於接口處,使意圖更加明了,同時又不增加調用者的負擔。

  再看一個例子:

復制代碼
import time,logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
is_debug = True

def count_time(is_debug):
    def handle_func(func):
        def handle_args(*args,**kwargs):
            if is_debug:
                begin = time.time()
                func(*args,**kwargs)
                logging.debug("[" + func.__name__ + "] -> " + str(time.time() - begin))
            else:
                func(*args,**kwargs)
        return handle_args
    return handle_func

def pr():
    for i in range(1,1000000):
        i = i * 2
    print 'hello world'

def test():
    pr()

@count_time(is_debug)
def test2():
    pr()

@count_time(False)
def test3():
    pr()

if __name__ == '__main__':
#    f()
#    g()
    test()
    test2()
    test3()
復制代碼

  參考:http://blog.csdn.net/wklken/article/details/8118942

6,with語句

  對於確保即使發生錯誤時也能運行一些清理代碼而言,try...finally語句是很有用的,對此有許多的場景,如:

  • 關閉一個文件
  • 釋放一個鎖
  • 創建一個臨時的代碼補丁
  • 在特殊環境中運行受保護的代碼

  with語句覆蓋了這些使用場景,為在一個代碼前后調用一些代碼提供了一種簡單的方法。例如,文本的讀取通常如下實現:

復制代碼
hosts = open('/etc/issus')

try:
    for line in hosts:
        if line.startswith('#')
            contine
        print line
finally:
    hosts.close()
復制代碼

  通過使用with語句,以上代碼可以重構如下:

復制代碼
from __future__ import with_statement

with open('/etc/issue') as hosts:
    for line in hosts:
        if line.startswith('#')
            continue
        print line
復制代碼

7,


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM