5.1 ลิสต์อีกที (More on Lists)
5.2 ประโยค del (The del statement)
5.3 ทูเปิล (Tuples and Sequences)
5.4 เซ็ต (Sets)
5.5 ดิกชันนารี (Dictionaries)
5.6 เทคนิกการวนรอบ (Looping Techniques)
5.7 เงื่อนไข (More on Conditions)
5.8 น้ำหนักของข้อมูลแบบลำดับ (Comparing Sequences and Other Types)
บทนี้จะอธิบายเทคนิกการใช้งานข้อมูล
เวลาใช้งานจริง เราจะใช้ลิสต์มากหน่อย เพราะมันเปลี่ยนแปลงค่าได้ เลยทำให้มีเมธอดของลิสต์เยอะหน่อย
append(x)a[len(a):] = [x]
>>> a=[1,2,3] >>> a.append(4) >>> a [1, 2, 3, 4]
extend(L)a[len(a):] = L
>>> a=[1,2,3] >>> L=[4,5,6] >>> a.extend(L) >>> a [1, 2, 3, 4, 5, 6]
insert(i, x)a.insert(0, x) ก็คือการไปแทรกข้างหน้าa.insert(len(a), x) ก็คือการไปต่อท้าย คือ a.append(x)>>> a=[1,2,3] >>> a.insert(2,0) >>> a [1, 2, 0, 3]
remove(x)>>> a=[1,2,3] >>> a.remove(2) >>> a [1, 3] >>> a.remove(2) Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: list.remove(x): x not in list
pop([i])>>> a=[1,2,3] >>> a.pop(1) 2 >>> a [1, 3]
index(x)>>> a=[1,2,3] >>> a.index(2) 1
count(x)>>> a=[2,2,2,9,4,4,4,4] >>> a.count(2) 3
sort()>>> a=[1,5,4,2,3] >>> a.sort() >>> a [1, 2, 3, 4, 5]
reverse()>>> a=[1,5,4,2,3] >>> a.reverse() >>> a [3, 2, 4, 5, 1]
ตัวอย่างรวมอีกทีนึง
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.25), a.count('x')
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]ถ้าจะใช้งานลิสต์แบบสแต็คคือ เข้าก่อนออกหลัง ก็แค่ใช้เมธอดให้เหมาะสม คือเติมด้วย append() แล้วเอาออกด้วย pop()
>>> stack = [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]
คือ เข้าก่อนออกก่อน ก็ใช้ append() และ pop(0) ตามลำดับ
>>> queue = ["Eric", "John", "Michael"]
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.pop(0)
'Eric'
>>> queue.pop(0)
'John'
>>> queue
['Michael', 'Terry', 'Graham']มี 3 ตัว (ไม่นับคำสั่ง lambda)
filter(function, sequence)sequence เฉพาะถ้า function คืนค่าที่เป็นจริง (ไม่ใช่ศูนย์หรือ None) งงนิดหน่อย ดูตัวอย่างดีกว่า เป็นการหาจำนวนเฉพาะ
>>> def f(x): return x % 2 != 0 and x % 3 != 0 ... >>> filter(f, range(2, 25)) [5, 7, 11, 13, 17, 19, 23]
map(function, sequence)sequence ไปทำงานใน function แล้วคืนช่วงของผลลัพธ์ออกมาเป็นลิสต์
>>> def cube(x): return x*x*x ... >>> map(cube, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
หาก function ต้องการอาร์กิวเมนต์มากกว่าหนึ่งตัว ก็ต้องใส่ sequence ด้วยจำนวนที่เท่ากัน
>>> seq = range(8) >>> def add(x, y): return x+y ... >>> map(add, seq, seq) [0, 2, 4, 6, 8, 10, 12, 14] >>> s2 = range(10,18) >>> map(add, seq, s2) [10, 12, 14, 16, 18, 20, 22, 24] >>> s3 = range(18, 10, -1) >>> map(add, seq, s3) [18, 18, 18, 18, 18, 18, 18, 18]
reduce(function, sequence)sequence ชุดแรก ไปเป็นข้อมูลนำเข้าให้ function กับ sequence ชุดต่อ ๆ ไป จนหมดข้อมูล
>>> def add(x,y): return x+y ... >>> reduce(add, range(1, 11)) 55
ถ้าไม่มีข้อมูลจาก sequence จะแสดงข้อผิดพลาด
>>> reduce(add, range(0)) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: reduce() of empty sequence with no initial value
เพื่อเป็นการป้องการการผิดพลาดดังกล่าว อาจใส่อาร์กิวเมนต์ตัวที่สามซึ่งจะกลายเป็นค่าเริ่มต้นให้กับ function เพื่อป้องกันกรณีลิสต์ว่าง ดังนี้
>>> def xsum(seq): ... def add(x,y): return x+y ... return reduce(add, seq, 0) ... >>> xsum(range(1, 11)) 55 >>> xsum([]) 0
เป็นโครงสร้างเฉพาะตัวของไพธอนที่ยืมมาจากภาษา Haskell/ML ในการสร้างลิสต์ใหม่จากลิสต์ที่มีอยู่ ใช้มากในไพธอน มีรูปแบบเป็น
[f(x) for x in L [ if p(x) ] ]
แปลว่า ให้สร้างลิสต์ด้วยฟังก์ชั่น f จากลิสต์ L สมาชิกต่อสมาชิก โดยแต่ละสมาชิกจะต้องมีค่า p(x) ที่เป็นจริง
โครงสร้างส่วนหลัง ตรงที่เป็น if ... เป็นตัวเลือก อาจใส่หรือไม่ก็ได้
ตัวอย่าง
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
>>> [3*x for x in vec if x > 3]
[12, 18]
>>> [3*x for x in vec if x < 2]
[]
>>> [[x,x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]
>>> [x, x**2 for x in vec] # error - parens required for tuples
File "<stdin>", line 1, in ?
[x, x**2 for x in vec]
^
SyntaxError: invalid syntax
>>> [(x, x**2) for x in vec]
[(2, 4), (4, 16), (6, 36)]
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
>>> [str(round(355/113.0, i)) for i in range(1,6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']del (The del statement)ใช้งานคล้าย ๆ pop() แต่เลือกช่วงได้ด้วย จึงต้องระบุดัชนีเสมอ
>>> a = [-1, 1, 66.25, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.25, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.25, 1234.5] >>> del a[:] >>> a []
สามารถใช้ del ในการลบตัวแปรได้ด้วย
>>> del a
ทูเปิลคล้ายกับลิสต์ ต่างกันตรงเป็นข้อมูลที่สามารถกำหนดค่าได้ครั้งเดียว จึงเหมาะที่จะใช้ในงานที่ต้องการค่าคงที่
ลิสต์ใช้วงเล็บก้ามปู [] แต่ทูเปิลใช้วงเล็บธรรมดา () หรืออาจละเลยไม่ใส่ก็ได้ โดยใส่แค่จุลภาค , ตามหลังสมาชิก (แต่ต้องระวังตัวเองงงเอง)
>>> 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))
ตัวอย่างการละเลยการใส่วงเล็บ ซึ่งถ้าดูผ่าน ๆ อาจสับสนได้
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton) # ได้ค่าเป็น 1 เพราะเป็นทูเปิลที่มีสมาชิก 1 ตัว
1
>>> singleton
('hello',)การละเลยการใส่วงเล็บในตอนกำหนดค่า ไพธอนเรียกว่า การอัดข้อมูลเป็นอนุกรม (sequence packing) ในกรณีนี้คือ tuple packing (ถ้าละเลยการใส่วงเล็บแล้ว จะถือว่าเป็นข้อมูล tuple เสมอ)
t = x, y, z
และยังสามารถกำหนดค่าแบบย้อนกลับได้ อันนี้เรียกว่า การแตกข้อมูลอนุกรม (sequence unpacking)
x, y, z = t
(ซึ่งถ้าเขียนให้ถูกจริง ๆ แล้วคือ (x, y, z) = t)
และแน่นอนว่าใช้กับลิสต์ได้เช่นเดียวกัน
[x, y, z] = t
ไพธอนรุ่นหลัง เติมความสามารถเรื่องเซ็ตเข้าไป ซึ่งเซ็ตก็คือลิสต์ที่สามารถใช้งานในลักษณะเซ็ตได้ เช่น การทำยูเนียนและอินเตอร์เซคเป็นต้น
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> fruit = set(basket) # create a set without duplicates
>>> fruit
set(['orange', 'pear', 'apple', 'banana'])
>>> 'orange' in fruit # fast membership testing
True
>>> 'crabgrass' in fruit
False
>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> a - b # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])เป็นชนิดข้อมูลพิเศษที่อยู่ในรูป {key: value, ...}
key อาจเป็นข้อมูลชนิดสคริง ตัวเลข หรือทูเปิลที่ไม่ได้บรรจุ multable object ไว้delkeys() ในการแสดงค่าคีย์ทั้งหมด และใช้เมธอด has_key() ในการค้นค่าคีย์>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> tel.keys()
['guido', 'irv', 'jack']
>>> tel.has_key('guido')
True
>>> 'guido' in tel
True
แปลงทูเปิลในลิสต์มาเป็นดิกชันนารีด้วยฟังก์ชั่น dict()
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>> dict([(x, x**2) for x in (2, 4, 6)]) # use a list comprehension
{2: 4, 4: 16, 6: 36}หรือหากค่าคีย์เป็นสตริงล้วน อาจกำหนดค่าแบบนี้ก็ได้ (เลียนแบบการส่งผ่านค่าไปยังฟังก์ชั่น)
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}iteritems()>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
... print k, v
...
gallahad the pure
robin the braveenumerate()>>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print i, v ... 0 tic 1 tac 2 toe
zip()>>> questions = ['name', 'quest', 'favorite color'] >>> answers = ['lancelot', 'the holy grail', 'blue'] >>> for q, a in zip(questions, answers): ... print 'What is your %s? It is %s.' % (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()>>> for i in reversed(xrange(1,10,2)): ... print i ... 9 7 5 3 1
sorted()>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana'] >>> for f in sorted(set(basket)): ... print f ... apple banana orange pear
while และ if ไม่จำเป็นต้องเป็นการเปรียบเทียบค่าเสมอไป แต่จะเป็นอะไรก็ได้ที่ ถ้าคืนค่าที่ไม่เป็นศุนย์หรือ None จะถูกนับว่าเป็นจริงin และ not in ใช้ดูว่ามีค่าอยู่ในลำดับข้อมูลหรือเปล่าis และ is not ใช้ดูว่าเป็นออปเจคต์เดียวกันหรือเปล่าa < b == c>>> True == 1 True >>> 1 < 2 == 1 False >>> 1 < 2 == 2 True
not สำคัญที่สุด และ or สำคัญน้อยที่สุด คือA and not B or C เขียนได้เป็น (A and (not B)) or C>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' >>> non_null = string1 or string2 or string3 >>> non_null 'Trondheim
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)