Python讀書筆記:細節決定成敗(1)

一個獨行的程式設計師發表於2016-01-14

感謝一個@一個獨行的程式設計師的投遞   來自一個獨行的程式設計師

背景:我本來是一個信奉Java大法好的程式設計師。但是最近由於工作原因,不得不開始學習python。因此,寫下這個讀書筆記,希望能起到一個拋磚引玉的作用。原文中所有引用部分均來自python官方的tutorial,傳送門:https://docs.python.org/2/tutorial/

1.[a:b)

在使用list時,我們會常常使用左右區間的位置來賦值(range)或刪除(del)其中的值。一定記住這個區間是一個左閉右開的區間;

>>>a = range(1,6)
>>>a
[1,2,3,4,5]
>>>del a[1,3]
>>> a
[1,4,5]

實際刪除的是1,2號元素,所以剩下的是[1,4,5]

2.Lambda表示式

如果使用過filter/map/reduce這幾個函式,就會知道lambda表示式真的在匿名函式的寫法上非常省時省力,且便於閱讀。舉個例子:

>>> filter(lambda x : x % 2 == 0, range(10))
[0, 2, 4, 6, 8]
>>> map(lambda x, y : x * y, range(1,4), range(1,4))
[1, 4, 9]
>>> reduce(lambda x, y : x + y, range(101))
5050

lambda表示式的用法也很簡單,“:”前寫明引數,後面寫表示式(函式體),表示式的結果就是函式返回值,這一點和R語言很像。

3.Tuples

A tuple consists of a number of values separated by commas

元組(tuples)在資料處理方面非常的powerful,因為它可以包含任意型別的變數,且可以巢狀,各個元素間用逗號分隔。但是,請注意:Tuples are immutable!(這一點和String一樣),但是他們可以包含mutable的變數。

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

u可以看作一個巢狀的tuple;v可以看做包含了2個list的tuple,而list是可以賦值的mutable變數;但是我們不能直接去修改tuple中元素的值,因為tuple本身是immutable的,搞清楚這一點很重要。

4.unpacking

unpacking應該和tuples結合起來看:如果將一個個變數裝進tuple中被稱作pack的話;那麼將tuple拆分成一個個獨立的變數就叫做unpack。

>>> t = 1, 2, ‘hello’
>>> t
(1, 2, ‘hello’)
>>> x, y, z = t
>>> x
1
>>> y
2
>>> z
‘hello’

值得注意的是:左邊的變數數量一定要與tuple中的元素數量一致!

Sequence unpacking requires the list of variables on the left to have the same number of elements as the length of the sequence.

5.Loop techniques

python對於迴圈的支援非常好,內建了很多有用的函式,這裡以enumerate(), zip(), reversed(), sorted(),iteritems()為例進行說明。

enumerate()

the position index and corresponding value can be retrieved at the same time using the enumerate() function.

可以在迴圈時同時取得下標位置和對應值

>>> for i, v in enumerate([‘tic’, ‘tac’, ‘toe’]):
…           print i, v

0 tic
1 tac
2 toe

zip()

To loop over two or more sequences at the same time, the entries can be paired with the zip() function.

在迴圈中如果有兩個幾以上的佇列時,可以通過zip函式進行對應的匹配

>>> questions = [‘name’, ‘quest’, ‘favorite color’]
>>> answers = [‘lancelot’, ‘the holy grail’, ‘blue’]
>>> for q, a in zip(questions, answers):
…           print ‘What is your {0}? It is {1}.’.format(q, a)

What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.

reversed()

To loop over a sequence in reverse, first specify the sequence in a forward direction and then call the reversed()function.

倒序輸出結果

>>> for i in reversed(xrange(1,10,2)):
…           print i

9
7
5
3
1

sorted()

To loop over a sequence in sorted order, use the sorted() function which returns a new sorted list while leaving the source unaltered.

遍歷後返回一個有序佇列,並且不修改原佇列。

>>> basket = [‘apple’, ‘orange’, ‘apple’, ‘pear’, ‘orange’, ‘banana’]
>>> for f in sorted(set(basket)):
…           print f

apple
banana
orange
pear

iteritems()

When looping through dictionaries, the key and corresponding value can be retrieved at the same time using the iteritems() method.

當遍歷dictionaries時,可以通過iteritems()來分別獲取key和value

>>> knights = {‘gallahad’: ‘the Pure’, ‘robin’: ‘the brave’}
>>> for k, v in knights.iteritems():
…           print k, v

gallahad the pure
robin the brave

6.Modules

很多人在開發時往往會涉及第三方package和多個指令碼的情況,但是其實很多時候有些細節上的東西沒有弄明白往往會出現事倍功半的效果。剩下兩節就好好講清楚Modules和Packages的關係,不感興趣的可以跳過。

A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended. Within a module, the module’s name (as a string) is available as the value of the global variable __name__.

module就是一個包含了一些定義(函式,類,變數,物件等)和語句的檔案,一般以”.py”作為字尾,編譯後的python檔案以”.pyc”作字尾。在module內,有一個全域性變數”__name__”,可以通過dir()函式來檢視當前環境中有哪些已定以的變數和函式。

以經典的fibonacci數列為例,假設下面這段程式碼是寫在”fibo.py”這個檔案中:

# Fibonacci numbers module

def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print b,
a, b = b, a+b

def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result

現在如果我們想要在命令列或者終端中使用這個函式,我們可以import這個module:

>>> import fibo
>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

你還可以給這個一個簡單的別名,使程式碼更簡潔:

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

7.Packages

(1)Packages are a way of structuring Python’s module namespace by using “dotted module names”.
(2)A package is A collection of modules

簡單來說,package就是一個有結構的module的集合,以便於實現某些特定功能和用途,比較出名的packages有:NumPy, PIL(Python Imaging Library)等等。

它與modules最大的不同在於import時的細節,一定要注意語法!

假設我們有個叫做”sound”的package,它主要用來處理多種不同格式的音訊檔案,如:mp3,wmv,wma等。它的結構如下:

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

python官方不建議import整個package,因為它會降低程式碼的可讀性。

Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code.

因此,我們有必要學會如何科學正確的import我們需要的submodule或subpackage.假設我們只需要echo.py這個module,我們可以單獨import它:

>>>import sound.effects.echo
>>>#This loads the submodule sound.effects.echo. It must be referenced with its full name. 必須使用全名去呼叫echo中的函式
>>>sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
>>>#An alternative way of importing the submodule is: 另一種import方法:
>>>from sound.effects import echo
>>>#This also loads the submodule echo, and makes it available without its package prefix, so it can be used as follows:通過from關鍵字,我們可以在呼叫時省去包名的字首
>>>echo.echofilter(input, output, delay=0.7, atten=4)

>>>#Yet another variation is to import the desired function or variable directly:如果你知道要呼叫什麼函式,甚至可以直接import這個函式
>>>from sound.effects.echo import echofilter
>>>#Again, this loads the submodule echo, but this makes its function echofilter() directly available:這樣的話,你就可以像呼叫本地函式一樣,省去所有字首
>>>echofilter(input, output, delay=0.7, atten=4)

通過三種import方法的對比,相信大家能夠根據自己的實際情況找到最適合自己的方法。

但是,這裡有一點語法上的細節,需要注意!

Note that when using from package import item, the item can be either a submodule (or subpackage) of the package, or some other name defined in the package, like a function, class or variable. The import statement first tests whether the item is defined in the package; if not, it assumes it is a module and attempts to load it. If it fails to find it, an ImportError exception is raised.

當使用from package import item這種語法結構時,item可以是一個submodule或subpackage,甚至是package中定義的一個函式,類和變數等物件;import會先假設item是一個物件,去測試其是否被定義;如果沒有找到,它會嘗試去載入,如果仍然沒有找到,那麼這時候會報ImportError

Contrarily, when using syntax like import item.subitem.subsubitem, each item except for the last must be a package; the last item can be a module or a package but can’t be a class or function or variable defined in the previous item.

相反,如果使用item.subitem.subsubitem這樣的語法結構時,除了最後一個item可以是module或者package以外,上級(字首)的所有item必須且只能是package,請謹記!

相關文章