1. 程式人生 > >我整理的Python代碼規則

我整理的Python代碼規則

同時 nbsp comm 內部 三個參數 自定義 更多 最後一個元素 undefine

首先,python有兩個版本,一個是Python2.X,一個是Python3.X,目前Python3.X越來越普及,這兩個版本是不兼容的,但由於我所用的大部分學習資料是用Python2.X的語法規則寫的,因而我整理的語法規則是基於Python2.X。我整理的部分基本上是我容易遺忘的地方。

數據類型:整數(%d),浮點數(%f),字符串(str)(%s),布爾值,空值,變量,常量 // -->地板除,除之後還是整數。Python的浮點數也沒有大小限制,但是超出一定範圍就直接表示為inf(無限大)。

字符串與編碼,對於單個字符的編碼,Python提供了ord()函數獲取字符的整數表示,chr()

函數把編碼轉換為對應的字符

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第二行註釋是為了告訴Python解釋器,按照UTF-8編碼讀取源代碼,否則,你在源代碼中寫的中文輸出可能會有亂碼。

有些時候,字符串裏面的%是一個普通字符怎麽辦?這個時候就需要轉義,用%%來表示一個%。

strbytes互相轉換時,需要指定編碼。最常用的編碼是UTF-8。Python當然也支持其他編碼方式,比如把Unicode編碼成GB2312。

Python內置的一種數據類型是列表:list。list是一種有序的集合,可以隨時添加和刪除其中的元素。list是一個可變的有序表

另一種有序列表叫元組:tuple。tuple和list非常類似,但是tuple一旦初始化就不能修改。

Python內置了字典:dict的支持,dict全稱dictionary,在其他語言中也稱為map,使用鍵-值(key-value)存儲,具有極快的查找速度。

set和dict類似,也是一組key的集合,但不存儲value。由於key不能重復,所以,在set中,沒有重復的key。

*args是可變參數,args接收的是一個tuple;

**kw是關鍵字參數,kw接收的是一個dict。

以及調用函數時如何傳入可變參數和關鍵字參數的語法:

可變參數既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過*args

傳入:func(*(1, 2, 3))

關鍵字參數既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過**kw傳入:func(**{‘a‘: 1, ‘b‘: 2})

使用*args**kw是Python的習慣寫法,當然也可以用其他參數名,但最好使用習慣用法。

命名的關鍵字參數是為了限制調用者可以傳入的參數名,同時可以提供默認值。

定義命名的關鍵字參數在沒有可變參數的情況下不要忘了寫分隔符*,否則定義的將是位置參數。

在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。

L[0:3]表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引012,正好是3個元素,如果第一個索引是0,還可以省略

前10個數,每兩個取一個:

>>> L[:10:2]

所有數,每5個取一個:>>> L[::5]


甚至什麽都不寫,只寫[:]就可以原樣復制一個list
使用內建的isinstance函數可以判斷一個變量是不是字符串

所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出後續的元素呢?這樣就不必創建完整的list,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。

要創建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator

如果要一個一個打印出來,可以通過next()函數獲得generator的下一個返回值

我們講過,generator保存的是算法,每次調用next(g),就計算出g的下一個元素的值,直到計算到最後一個元素,沒有更多的元素時,拋出StopIteration的錯誤。

當然,上面這種不斷調用next(g)實在是太變態了,正確的方法是使用for循環,因為generator也是可叠代對象:

fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出後續任意的元素,這種邏輯其實非常類似generator。也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只需要把print(b)改為yield b就可以了

我們已經知道,可以直接作用於for循環的數據類型有以下幾種:

一類是集合數據類型,如listtupledictsetstr等;

一類是generator,包括生成器和帶yield的generator function。

這些可以直接作用於for循環的對象統稱為可叠代對象:Iterable

listdictstrIterable變成Iterator可以使用iter()函數

你可能會問,為什麽listdictstr等數據類型不是Iterator

這是因為Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用並不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。

Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。

我們先看map。map()函數接收兩個參數,一個是函數,一個是Iterablemap將傳入的函數依次作用到序列的每個元素,並把結果作為新的Iterator返回

再看reduce的用法。reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

Python內建的filter()函數用於過濾序列。

map()類似,filter()也接收一個函數和一個序列。和map()不同的是,filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。

例如,在一個list中,刪掉偶數,只保留奇數,可以這麽寫:

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 結果: [1, 5, 9, 15]

註意到filter()函數返回的是一個Iterator,也就是一個惰性序列,所以要強迫filter()完成計算結果,需要用list()函數獲得所有結果並返回lis
默認情況下,對字符串排序,是按照ASCII的大小比較的,由於‘Z‘ < ‘a‘,結果,大寫字母Z會排在小寫字母a的前面
sorted()函數也是一個高階函數,它還可以接收一個key函數來實現自定義的排序,例如按絕對值大小排序
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

要進行反向排序,不必改動key函數,可以傳入第三個參數reverse=True
高階函數除了可以接受函數作為參數外,還可以把函數作為結果值返回。
當我們在傳入函數時,有些時候,不需要顯式地定義函數,直接傳入匿名函數更方便。
函數對象有一個__name__屬性,可以拿到函數的名字

現在,假設我們要增強now()函數的功能,比如,在函數調用前後自動打印日誌,但又不希望修改now()函數的定義,這種在代碼運行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。

本質上,decorator就是一個返回函數的高階函數。所以,我們要定義一個能打印日誌的decorator,可以定義如下:

def log(func):
    def wrapper(*args, **kw):
        print(‘call %s():‘ % func.__name__)
        return func(*args, **kw)
    return wrapper

觀察上面的log,因為它是一個decorator,所以接受一個函數作為參數,並返回一個函數。

Python的functools模塊提供了很多有用的功能,其中一個就是偏函數(Partial function)

所以,簡單總結functools.partial的作用就是,把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數,調用這個新函數會更簡單。

註意到上面的新的int2函數,僅僅是把base參數重新設定默認值為2,但也可以在函數調用時傳入其他值。當參數過多需要化簡,對某些值進行固定可以使用該原理。

Python本身就內置了很多非常有用的模塊,只要安裝完畢,這些模塊就可以立刻使用。

在一個模塊中,我們可能會定義很多函數和變量,但有的函數和變量我們希望給別人使用,有的函數和變量我們希望僅僅在模塊內部使用。在Python中,是通過_前綴來實現的。

類似__xxx__這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,比如上面的__author____name__就是特殊變量,hello模塊定義的文檔註釋也可以用特殊變量__doc__訪問,我們自己的變量一般不要用這種變量名。

類似_xxx__xxx這樣的函數或變量就是非公開的(private),不應該被直接引用,比如_abc__abc

 

我整理的Python代碼規則