高見龍

iOS app/Ruby/Rails Developer & Instructor, 喜愛非主流的新玩具 :)

Tuple

元組

Tuple有人把它翻譯成"元組",不過我個人還是習慣用英文來稱呼它。

List用中括號、Dictionary用大括號,Tuple則是使用小括號。Tuple長的像這樣:

1
('a', 1, "bbbccc")

其實Tuple跟List很像,只是它的內容一旦設定後就不可改變了。也因為Tuple跟List很像,除了一些修改/刪除的操作是不行的之外,其它很多操作都跟List差不多:

>>> my_tuple = (1, 2, 3)
>>> my_tuple[0]
1
>>> my_tuple[0] = "x"
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

要注意的是,如果Tuple只有一個元素的話,結尾需要加上逗號

1
(element, )

Dictionary

字典

有的程式語言稱它叫"Hash Table",有的管它叫做"物件",基本上Python的Dictionary就長這個樣子:

1
eddie = {"first_name" : "eddie", "last_name" : "kao", "age" : 30}

List是用中括號,Dictionary則是使用大括號。Dictionary是由Key及Value之配對組合而成,順序不重要,但Key的大小寫有分別。跟List一樣,並不限定只能放同一種型態的資料。

Nested Dictionary

可以一層包一層..

1
author = { "name" : "eddie", "profile" : {"age" : 30, "tel" : "0928123456"} }

操作

來看看怎麼操作Dictionary。

取用

>>> my_dict = {'first_name': 'eddie', 'last_name': 'kao', 'age': 30}
>>> my_dict["first_name"]
'eddie'

新增

>>> my_dict = {'first_name': 'eddie', 'last_name': 'kao', 'age': 30}
>>> my_dict["weight"] = 80
>>> my_dict
{'first_name': 'eddie', 'last_name': 'kao', 'age': 30, 'weight': 80}

修改

>>> my_dict = {'first_name': 'eddie', 'last_name': 'kao', 'age': 30}
>>> my_dict['last_name'] = 'lee'
>>> my_dict
{'first_name': 'eddie', 'last_name': 'lee', 'age': 30}

刪除/清空

>>> my_dict = {'first_name': 'eddie', 'last_name': 'lee', 'age': 30}
>>> my_dict.clear()
>>> my_dict
{}
>>> del my_dict
>>> my_dict
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
NameError: name 'my_dict' is not defined

其它

  1. len : 檢查Dict的個數
  2. in / not in : 檢查是某個Key否存在該dictionary裡,回傳Boolean值
  3. copy : 將Dict之內容複製至另一變數
  4. has_key : 檢查是否有某個Key存在,回傳Boolean值
  5. items : 將Dict的key/value拆成Tuple之組合,回傳List
  6. keys : 將Dict的key部份回傳成List
  7. values : 將Dict的value部份回傳成List
  8. get : 取得指定key的值,第二個參數則是指定當找不到該key的導候所回傳的預設值

千言萬語,抵不過直接看程式碼:

>>> my_dict = {'first_name': 'eddie', 'last_name': 'kao', 'age': 30, 'weight': 80}
>>> len(my_dict)
4
>>> "eddie" in my_dict
False
>>> "first_name" in my_dict
True
>>> my_dict.has_key("age")
True
>>> my_dict.items()
[('first_name', 'eddie'), ('last_name', 'kao'), ('age', 30), ('weight', 80)]
>>> my_dict.keys()
['first_name', 'last_name', 'age', 'weight']
>>> my_dict.values()
['eddie', 'kao', 30, 80]
>>> my_dict.get("age")
30
>>> my_dict.get("height", 180)
180

本是同根生..

當在處理像List或是Dictionary這種比較複雜的資料結構的時候,有個新手可能常會犯的錯誤,我們來看一段程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a = [1, 2, 3]
b = a

b[0] = 'x'

print b                  # ['x', 2, 3]
print a                  # ['x', 2, 3]

x = {"name" : "eddie"}
y = x

y["name"] = "kao"

print y                  # {"name" : "kao"}
print x                  # {"name" : "kao"}

i = j = [1, 2, 3]
i[0] = 'a'

print i                  # ['a', 2, 3]
print j                  # ['a', 2, 3]

注意到了嗎? 第2行、第10行、第17行的把某變數指定給另一個變數,但修改過新的變數的值之後,舊的變數的內容也跟著改了! 這是因為其實那個指定的動作只是個「請把b變數指向a」而已,所以遇到這種有"內容物"的資料型態,例如List跟Dictionary,當修改了b的值之後,a的值也跟著變了,因為他們兩個根本就是指到同一個地方。

這在Tuple就沒問題啦,因為Tuple是唯讀的。

那如果想讓兩個變數各保有原來的值而不互相影響呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = [1, 2, 3]
b = a[:]

print b          # [1, 2, 3]

b[0] = 'a'

print b          # ['a', 2, 3]
print a          # [1, 2, 3]

x = {"name" : "eddie"}
y = x.copy()

print y          # {'name' : 'eddie'}

y['name'] = 'kao'

print y          # {'name' : 'kao'}
print x          # {'name' : 'eddie'}

就是複製一份並指令給新的變數囉! 不過這遇上巢狀結構還是會有出狀況,因為[:]或是Dictiony內建的copy()方法只會複製最表層而已,內部巢狀結構還是會有一樣的狀況。如果要整個完全複製,請使用copy模組的deepcopy(),細節請參考官網文件:http://docs.python.org/library/copy.html

更多精彩內容,請見官網文件:http://docs.python.org/tutorial/datastructures.html

List

陣列?

你也許會好奇在Python裡有沒有像其它語言一樣叫做陣列(Array)的東西。在Python並沒有名叫"Array"的東西,但有個叫做"List"(串列)的資料結構,用起來跟在其它語言的陣列是差不多,不過它的功能比一般其它語言的陣列要來得更便利。

是有順序的!

List的定義是使用中括號,裡面不限定只能放數字或文字,你要放物件也可以。

1
my_list = [1, 2, 3, 4, 5, "aa", "bb"]

List是有順序的,所以如果你要取用List裡的第1項東西的話:

1
print my_list[0]

操作

接下來我們來看看在List有哪些常用的操作。

又是切割!

>>> my_list[1:3]
[2, 3]

>>> my_list[:-1]
[1, 2, 3, 4, 5, 'aa']

>>> my_list[:]
[1, 2, 3, 4, 5, 'aa', 'bb']

新增元素

  1. append 在最後面加入元素,不用產生新物件,速度會比用+快一點
  2. insert 在指定的位置插入新的元素
  3. extend 在最後面加入元素
  4. + 把兩個List給加在一起

你可能會好奇appendextend有什麼不一樣,我們來看看實際操作:

>>> my_list = [1, 2, 3, 4, 5, "aa", "bb"]
>>> my_list.append(123)
>>> my_list
[1, 2, 3, 4, 5, 'aa', 'bb', 123]
>>> my_list.insert(1, "x")
>>> my_list
[1, 'x', 2, 3, 4, 5, 'aa', 'bb', 123]
>>> my_list.extend(['a', 'b', 'c'])
>>> my_list
[1, 'x', 2, 3, 4, 5, 'aa', 'bb', 123, 'a', 'b', 'c']

可以看到extend會把塞進去的元素先展開再貼到最後面,而append只是把給它的元素直接放到最後面而已。

搜尋

直接看程式碼比較容易理解:

>>> my_list = [1, 2, 3, 4, 5, "aa", "bb"]
>>> my_list.index("aa")
5
>>> "bb" in my_list
True
>>> "eddie" in my_list
False

刪除

>>> my_list = [1, 2, 3, 4, 5, "aa", "bb"]
>>> my_list.pop()
'bb'
>>> my_list
[1, 2, 3, 4, 5, 'aa']
>>> my_list.remove("aa")
>>> my_list
[1, 2, 3, 4, 5]
>>> my_list.remove("bb")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list

Range

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

組合與拆解

>>> my_str_list = ["hello", "python", "good morning"]
>>> "-".join(my_str_list)
'hello-python-good morning'
>>> my_str = 'hello-python-good morning'
>>> my_str.split('-')
['hello', 'python', 'good morning']

排序、反轉

>>> my_list = [1, 2, 5, 8, 3, 0]
>>> my_list.sort()
>>> my_list
[0, 1, 2, 3, 5, 8]
>>> my_list.reverse()
>>> my_list
[8, 5, 3, 2, 1, 0]

List Comprehension

這個是Python的List的一個很棒的功能,可以讓你的程式碼變得更精簡,直接來看範例:

>>> print [i for i in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> print [i for i in range(20) if i%2 == 0]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

更多精彩內容,請見官網文件http://docs.python.org/tutorial/datastructures.html

字串

最常用的資料型態

不管在哪種程式語言,字串大概都是使用量最大的資料型態。

單引號跟雙引號的差別?

其實沒什麼差別。

操作

接下來我們看一些常見的字串操作

字串替換

1
2
3
4
5
>>> "%s = %s" % ("eddie", "kao")
'eddie = kao'

>>> "my name is %(name)s" % {'name' : 'eddie'}
'my name is eddie'

字串格式化

1
2
3
4
5
6
7
8
>>> "my name is %10s" % "eddie"
'my name is      eddie'

>>> "my name is %-10%" % eddie"
'my name is eddie     '

>>> "the PI is %.3f" % 3.1415926
'the PI is 3.142'

len() 字串長度

1
2
3
>>> greeting = "hello, eddie"
>>> len(greeting)
12

算字串的長度,其實就是算有幾個字元..

字串的"運算"?

字串也可以用加號+跟乘號*,不過並不是真的像數字一樣的四則運算:

“+”(加號)

1
2
>>> print "eddie" + "kao"
eddiekao

“*”(乘號)

1
2
>>> print "eddie"*3
eddieeddieeddie

有人在嗎?

使用in語法,可以檢查該字串是否包含某個字元:

1
2
3
4
>>> "a" in "abcdefg"
True
>>> "x" in "abcdefg"
False

切割

split

1
2
3
>>> my_str = "xxx yyy zzz"
>>> my_str.split()
['xxx', 'yyy', 'zzz']

slice

1
2
3
4
5
6
7
8
9
10
11
12
>>> my_str = "abcdefg"
>>> print my_str[0]
a

>>> print my_str[-1]
g

>>> print my_str[1:4]
bcd

>>> print my_str[:-1]
abcdef

中文字元怎麼切? 怎麼算?

1
2
3
4
5
6
7
8
9
# encoding: utf-8
my_name = "高見龍"
my_name_unicode = u"高見龍"

print len(my_name)           # 9
print len(my_name_unicode)   # 3

for word in my_name_unicode:
  print word

注意到前面那個小寫的u嗎? 加上u表示這個字串是unicode的,這樣一來在算字數時候,每個中文字就會被當做一個字元來計算了。

Python的字串還有很多可以介紹的,不過因為我們主要的目的是Django,所以不會打算把所有的字串方法都一一介紹一次,更多細節,請見官網文件:http://docs.python.org/library/string.html (這是個重要的章節,為了你的將來,請一定要看!)

再來,我們來看看在Python的串列(List)..

Boolean

Boolean? 真的假的?

Boolean值很單純,只有兩種結果,就是真的(True)跟假的(False),不是真的就是假的,沒有灰色地帶。

哪些東西是假的?

  • 0 數字0
  • ”” 空字串
  • [] 空的List
  • () 空的Tuple
  • {} 空的Dict
  • None
  • 當然還有False本身也是假的..

因為真的(True)太多種,沒辦法用窮舉法一項一項列出來,所以我們只要記得哪些是假的(False),然後只要不是假的,就是真的。

要注意的是,在Python,程式碼是有大小寫之分的,所以如果寫成false的話,是認不出來的。

接下來,我們來看看很常使用的字串..