少年幃禿的煩惱

Navigation

最新協作平台活動

72天前是
某個日子

Home‎ > ‎Python‎ > ‎

Dive Into Python

安裝 Python

在 Windows 上可以從 Python.org 下載安裝. 安裝好之後執行 IDLE (Python GUI) 或是 Python (command line) 都可以開啟 shell, 可以嘗試著在上面進行一些操作.

>>> 1 + 1
2
>>> print 'hello world'
hello world
>>> x = 1
>>> y = 2
>>> x + y
3

第一個 Python 程式

# odbchelper.py
def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.

    Returns string."""
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

if __name__ == "__main__":
    myParams = {"server":"mpilgrim", \
                "database":"master", \
                "uid":"sa", \
                "pwd":"secret" \
                }
    print buildConnectionString(myParams)

執行 odbchelper.py 的輸出結果 : server=mpilgrim;uid=sa;database=master;pwd=secret

函數宣告

Python 的函數宣告方法

def buildConnectionString(params):

函數宣告, 首先以關鍵字 def 開始, 接著是函數名稱, 參數放在小括號裡面, 多個函數之間則是用逗號分隔開來. 而且不需要定義返回的資料型態. 實際上, 每個 Python 都有返回一個值, 如果函數內有 return 語句, 則返回指定的值, 否則就返回 None (Python 的空值).

函數文件

可以透過指定 doc string 來建立 Python 函數的文件

def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.

    Returns string."""

三個引號代表一個多行的字串. 在開始與結束的引號之間所有的東西都是屬於單個字串的一部分, 可以在任何地方使用, 但是通常被用於定義 doc string.

doc string 是用來說明函數可以做什麼, 如果存在 doc string 的話, 他必須是一個函數要定義的第一個內容(也就是說, 在冒號後面的第一個內容). 在技術上不要求給出函數的 doc string, 但是最好這麼做.

所有東西都是物件

Python 函數是有屬性的, 而且這些屬性在運行時是可用的. 函數跟其他東西一樣都是物件, 那麼你可以執行以下的操作:

>>> import odbchelper
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> print odbchelper.buildConnectionString(params)
server=mpilgrim;uid=sa;database=master;pwd=secret
>>> print odbchelper.buildConnectionString.__doc__
Build a connection string from a dictionary

Returns string.

在 Python 的 import 就像 Perl 中的 require. import 一個 Python module 後, 就可以使用 module.function 來訪問他的函數. require 一個 Perl module 後, 就可以使用 module::function 來訪問他的函數.


引用的搜尋路徑

import module 的時候, Python 會在幾個地方進行搜尋. 更明確的來說, 他會對定義在 sys.path 中的目錄逐個進行搜尋. 這是一個 list, 所以可以經由標準的 list 方法來修改.

>>> import sys
>>> sys.path
['', '/usr/local/lib/python2.2', '/usr/local/lib/python2.2/plat-linux2',
'/usr/local/lib/python2.2/lib-dynload', '/usr/local/lib/python2.2/site-packages',
'/usr/local/lib/python2.2/site-packages/PIL', '/usr/local/lib/python2.2/site-packages/piddle']
>>> sys
<module 'sys' (built-in)>
>>> sys.path.append('/my/new/path')

sys 並非一般的 .py 檔案, 他是屬於 Python 內建的 module. 內建的 module 行為跟一般 module 是一樣的, 但是他的 Python 原始碼不可以直接使用, 因為他們不是用 Python 寫的. ( sys module 是用 C 寫的)

程式縮排

Python 函數並沒有明顯的 begin 與 end, 沒有標明函數開始與結束的大括號. 唯一個分隔符號是一個冒號 (:), 接著就是程式的縮排了.

def buildConnectionString(params):
    """Build a connection string from a dictionary of parameters.

    Returns string."""
    return ";".join(["%s=%s" % (k, v) for k, v in params.items()])

程式區塊是通過縮排來定義的. 這邊的程式區塊指的是: 函數, if 語句, for 循環, while 循環...等等. 開始縮排表示區塊的開始, 取消縮排表示區塊的結束. 並沒有明顯的大小括號或是關鍵字. 這就意味著空白的重要了, 而且要一致. 在這個例子中, 程式碼(包含 doc string) 縮進了 4 個空格. 並非一定要 4 個, 只要一致就可以了. 沒有縮排的第一行則被視為在函數區塊之外.

原生資料類型

Dictionary 介紹

Dictionary 是 Python 的原生資料類型之一, 它定義了 key 和 value 之間一對一的關係.
>>> d = {"server":"mpilgrim", "database":"master"}
>>> d
{'database': 'master', 'server': 'mpilgrim'}
>>> d["server"]
'mpilgrim'
>>> d["foo"]
Traceback (most recent call last):
  File "<input>", line 1, in <module>
KeyError: 'foo'
當使用一個不是 key 的時候會出現例外錯誤.

修改 Dictionary
>>> d
{'database': 'master', 'server': 'mpilgrim'}
>>> d["database"] = "pubs"             # key 不可重複, 所以會覆蓋掉原本的值
>>> d
{'database': 'pubs', 'server': 'mpilgrim'}
>>> d["encoding"] = "utf-8"            # 加入新的值
>>> d
{'encoding': 'utf-8', 'database': 'pubs', 'server': 'mpilgrim'}

刪除 dictionary
>>> d
{'encoding': 'utf-8', 'database': 'pubs', 'server': 'mpilgrim'}
>>> del d['encoding']                  # 使用 del 刪除
>>> d
{'database': 'pubs', 'server': 'mpilgrim'}

>>> d.clear()                                                    # 使用 clear() 方法
>>> d
{}

List 介紹

List 是一個用中括號包括起來的有序元素集合.
>>> li = ["a", "b", "foo", "bar"]
>>> li
['a', 'b', 'foo', 'bar']
>>> li[0]
'a'
>>> li[3]
'bar'


list 的 slice
>>> li
['a', 'b', 'foo', 'bar']
>>> li[1:3]            # 從第 1 個 slice 索引開始, 但是不包括第 2 個 slice 索引
['b', 'foo']

>>> li[:3]             # slice 的縮寫, 第 1 個預設為 0
['a', 'b', 'foo']
>>> li[3:]                          # slice 的縮寫, 第 2 個預設 list 長度
['bar']

向 list 中增加元素
>>> li
['a', 'b', 'foo', 'bar']

>>> li.append("new")                     # list 最後追加單個元素                                   
>>> li
['a', 'b', 'foo', 'bar', 'new']

>>> li.insert(2, "new")                                  # 插入元素到指定的索引, list 的 value 是可以重複的
>>> li
['a', 'b', 'new', 'foo', 'bar', 'new']
>>> li.extend(["one", "two"])                        # 連接 list
>>> li
['a', 'b', 'new', 'foo', 'bar', 'new', 'one', 'two']

搜索 list
>>> li
['a', 'b', 'new', 'foo', 'bar', 'new', 'one', 'two']
>>> li.index("new")                                            # 傳回 首次 出現的 "new"
2
>>> li.index("c")
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: list.index(x): x not in list
>>> "c" in li                                                        # 使用 in 來檢查是否存在 list 內
False

從 list 中刪除元素
>>> li
['a', 'b', 'new', 'foo', 'bar', 'new', 'one', 'two']
>>> li.remove("new")                 # 只會移除 第一個找到的 "new"
>>> li
['a', 'b', 'foo', 'bar', 'new', 'one', 'two']
>>> li.remove("c")                   # 例外錯誤
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> li.pop()                         # pop 會做兩件事情, 刪除最後一個元素, 返回被刪除的元素
'two'
>>> li
['a', 'b', 'foo', 'bar', 'new', 'one']


List 運算符
>>> li = ['a', 'b', 'c']
>>> li += ['one', 'two']        # list = list + otherlist 等於 list.extend(otherlist)
>>> li
['a', 'b', 'c', 'one', 'two']
>>> li = [1, 2] * 3
>>> li
[1, 2, 1, 2, 1, 2]

Tuple 介紹

Tuple 是不可變的 list. 一但建立了一個 tuple, 不就能以任何方式改變他.
>>> t = ('a', 'b', 'c')
>>> t
('a', 'b', 'c')


Tuple 沒有方法
>>> "z" in t
False
tuple 不能新增, 刪除, 尋找元素. 但是可以用 in 來檢查元素是否存在於 tuple 之中. tuple 的處理速度比 list 快.

自省

使用 type, str, dir 和其他內建函數

>>> type(1)                            # type 可以接受任何東西作為參數, 並返回他的數據類型.
<type 'int'>
>>> type([])
<type 'list'>
>>> import sys
>>> type(sys)
<type 'module'>
>>> import types
>>> type(sys) == types.ModuleType
True

str 函數

str 將資料強制轉換成 string
>>> str(1)                     
'1'
>>> str(sys)
"<module 'sys' (built-in)>"
>>> str(None)
'None'

dir 介紹

dir 函數返回任意對象的屬性和方法列表, 包括模塊對象, 函數對象, 字符串對象, 列表對象, 字典對象....相當多的東西.
>>> dir([])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

callable 介紹

callable 接收任何對象作為參數, 如果參數對象是可調用的, 返回 True, 否則返回 False
>>> import string
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> string.join
<function join at 0xa01d33c>
>>> callable(string.punctuation)
False
>>> callable(string.join)
True

過濾列表

過濾列表語法:   [mapping-expression for element in source-list if filter-expression]
>>> li = ['a', 'mpilgrim', 'foo', 'b', 'c', 'd', 'd', 'd']
>>> [elem for elem in li if len(elem) > 1]        # 長度 > 1
['mpilgrim', 'foo']
>>> [elem for elem in li if elem != 'b']          # 不等於 "b"
['a', 'mpilgrim', 'foo', 'c', 'd', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1]  # 只出現一次的
['a', 'mpilgrim', 'foo', 'b', 'c']

and 和 or 的特殊性質

在 Python 中, and 和 or 執行布爾邏輯運算, 如你所預期的一樣. 但他並不返回布爾值, 而是返回他實際進行比較的值之一.
>>> 'a' and 'b'               # 所有值都為真, 那麼 and 返回最後一個值.
'b'
>>> '' and 'b'                
# 0, '', [], (), {}, None 在布爾環境中為假. 其他任何東西都為真.
''
>>> 'a' and 'b' and 'c'
'c'
>>> 'a' or 'b'                # 使用 or 時, 如果有一個值為真, or 立即返回該值.
'a'
>>> '' or 'b'
'b'
>>> '' or [] or {}            # 所有值都為假, or 返回最後一個假值
{}

使用 and-or 技巧
>>> a, b = 'first', 'second'
>>> 1 and a or b
'first'
>>> 0 and a or b
'second'
當 a 為假時, 這個表達式就不會按你預期了.

and-or 技巧無效的場合
>>> a, b = '', 'second'
>>> 1 and a or b
'second'


安全使用 and-or 技巧
>>> a, b = '', 'second'
>>> (1 and [a] or [b])[0]
''

由於 [a] 是一個非空列表, 所以他絕不會為假. 即使 a 是 0 或是 '' 或者其他假值, 列表 [a] 也為真, 因為他有一個元素.

使用 lambda 函數

>>> def f(x):
...    return x*2
...   
>>> f(3)
6
>>> g = lambda x: x * 2
>>> g(3)
6
>>> (lambda x: x * 2)(3)
6