ไฟล์ทั้งหมดที่ใช้และสร้างที่เกี่ยวข้องขณะเข้าร่วมการฝึกทักษะวิจัยที่ NECTEC สวทช.
โดย Prachya Boonkwan and Patsagorn Yuenyong, CC-BY-SA-3.0
ปรัชญา บุญขวัญ
Email: prachya.boonkwan@nectec.or.th
(C) December 2018
append
insert
extend
del
ลิสต์ (list) คือรายการสิ่งของที่เราสามารถปรับเปลี่ยนรายการได้ตลอดเวลาครับ
ลิสต์ใช้สัญลักษณ์ [ ]
คั่นด้วยเครื่องหมายคอมมา ,
คำสั่งเข้าถึงสมาชิก (indexing): เราสามารถเข้าถึงสมาชิกแต่ละตัวในลิสต์ด้วยการระบุตำแหน่งของสมาชิกที่เราต้องการ ด้วยคำสั่ง [
$i$ ]
เมื่อ $i$ คือ index ที่เราต้องการเข้าถึง ซึ่งเริ่มนับจาก 0 เสมอ
คำสั่งเลือกบางส่วน (slicing): ลิสต์[
$a$ :
$b$ ]
จะเลือกสมาชิกตั้งแต่ index ที่ $a$ จนถึง index ที่ $b - 1$
ตัวอย่าง: หากเรามีลิสต์ของคะแนนสอบนักเรียน scores
เราสามารถหาช่วงของคะแนน ตั้งแต่คะแนนสูงกว่า 80 คะแนนตำแหน่งแรก จนถึงคะแนนสูงกว่า 80 คะแนนตำแหน่งสุดท้ายได้ด้วยโปรแกรมนี้
scores = [35.5, 73.0, 83.5, 65.0, 81.0, 79.5, 87.0, 49.5]
print(scores, end='\n\n')
print('Finding the first high-score...')
begidx = 0
for i in range(len(scores)):
print('Score:', scores[i])
if scores[i] > 80.0:
begidx = i
break
print('First high-score index:', begidx, end='\n\n')
print('Finding the last high-score...')
endidx = len(scores)
for i in range(len(scores) - 1, -1, -1):
print('Score:', scores[i])
if scores[i] > 80.0:
endidx = i
break
print('Last high-score index:', endidx, end='\n\n')
print('Score slice:', scores[begidx : endidx + 1])
[35.5, 73.0, 83.5, 65.0, 81.0, 79.5, 87.0, 49.5]
Finding the first high-score...
Score: 35.5
Score: 73.0
Score: 83.5
First high-score index: 2
Finding the last high-score...
Score: 49.5
Score: 87.0
Last high-score index: 6
Score slice: [83.5, 65.0, 81.0, 79.5, 87.0]
append
คำสั่ง insert
และคำสั่ง extend
del
sort
และ sorted
append
append
: เราจะนำสมาชิกใหม่ต่อท้ายลิสต์ด้วยคำสั่ง ลิสต์.append(
$e$ )
เมื่อ $e$ คือสมาชิกใหม่ตัวนั้นmy_numbers
ได้ดังนี้my_numbers = [11, 12, 13, 14, 15]
for i in range(1, 6):
my_numbers.append(i)
print(my_numbers)
[11, 12, 13, 14, 15, 1, 2, 3, 4, 5]
จงนำสมาชิกแต่ละตัวในลิสต์ new_numbers
ไปต่อท้ายลิสต์ my_numbers
ด้วยคำสั่ง append
และแสดงลิสต์ my_numbers
ออกหน้าจอ
my_numbers = [1, 2, 3, 4, 5]
new_numbers = [11, 12, 13, 14, 15]
for element in new_numbers:
my_numbers.append(element) # แก้ไขโค้ดที่นี่
print(my_numbers)
[1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
insert
insert
: เราจะแทรกสมาชิกใหม่เข้าไปใน index ที่กำหนดด้วยคำสั่ง ลิสต์.insert(
$i$ ,
$e$ )
เมื่อ $i$ คือ index ที่เราจะแทรกสมาชิกใหม่ลงไป และ $e$ คือสมาชิกใหม่ตัวนั้นmy_numbers = [20, 40, 60, 80, 100]
my_numbers.insert(2, 70)
print(my_numbers)
[20, 40, 70, 60, 80, 100]
จงเพิ่มสมาชิกใหม่ลงในลิสต์ my_numbers
ตามรายการดังต่อไปนี้
แล้วจึงแสดงลิสต์ my_numbers
ออกที่หน้าจอ
my_numbers = [20, 40, 60, 80, 100]
# แทรกเลข 50 ที่ index 1
my_numbers.insert(1, 50) # แก้โค้ดที่นี่
# แทรกเลข 70 ที่ index 3
my_numbers.insert(3,70) # แก้โค้ดที่นี่
# แทรกเลข 90 ที่ index 5
my_numbers.insert(5,90) # แก้โค้ดที่นี่
print(my_numbers)
[20, 50, 40, 70, 60, 90, 80, 100]
ผลลัพธ์ที่ได้ควรจะเป็น [20, 50, 40, 70, 60, 90, 80, 100]
นะครับ
หากเราแทรกตัวเลข 11 ถึง 15 เข้าไปที่ต้นลิสต์ my_numbers
(คือ index ที่ 0) เราจะได้ผลลัพธ์ดังนี้
my_numbers = [1, 2, 3, 4, 5]
new_numbers = [11, 12, 13, 14, 15]
for i in new_numbers:
my_numbers.insert(0, i)
print(my_numbers)
[15, 14, 13, 12, 11, 1, 2, 3, 4, 5]
จะสังเกตได้ว่า ตัวเลข 11 ถึง 15 ที่ด้านบนยังคงเรียงลำดับจากมากไปน้อยอยู่ เรามาแก้ไขโปรแกรมด้านบนเพื่อให้ตัวเลข 11 ถึง 15 เรียงลำดับจากน้อยไปมากกันดีกว่าครับ
my_numbers = [1, 2, 3, 4, 5]
new_numbers = [11, 12, 13, 14, 15]
for i in range(len(new_numbers)):
my_numbers.insert(i, new_numbers[i]) # แก้ไขโค้ดที่นี่
print(my_numbers)
[11, 12, 13, 14, 15, 1, 2, 3, 4, 5]
ผลลัพธ์ที่ได้ควรจะเป็นดังนี้ครับ [11, 12, 13, 14, 15, 1, 2, 3, 4, 5]
จงเขียนโปรแกรมเพื่อเรียงลำดับข้อมูลด้วยแอลกอริธึม Insertion Sort
หลักการของ insertion sort เปรียบเสมือนการเรียงไพ่ในมือ เวลาที่เราเล่นไพ่ หลังจากที่เราจั่วไพ่ขึ้นมา เราจะนำไพ่ใบนั้นมาเทียบกับไพ่แต่ละใบในมือ หากไพ่ที่จั่วได้มามีค่าน้อยกว่าไพ่ใบไหนในมือ เราก็จะนำไพ่ใบใหม่ไปแทรกที่ตำแหน่งนั้น
เราจะจั่วไพ่แบบนี้ไปเรื่อยๆ จนกว่าไพ่จะหมดกอง สิ่งที่ได้คือไพ่ในมือของเราจะเรียงลำดับตามหน้าไพ่ครับ
ในแบบฝึกหัดนี้เราจะมาเขียนโปรแกรมเรียงลำดับตัวเลข โดยใช้หลักการเดียวกันการเรียงไพ่ในมือนะครับ
# กองไพ่
items = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
# ไพ่ที่อยู่ในมือ
result = []
# จั่วไพ่จากกองออกมาทีละใบ
for new_item in items:
# ตัวแปรนี้มีไว้ตรวจสอบว่า เราแทรกไพ่ที่จั่วมาลงในมือได้หรือยัง
is_inserted = False
# ไล่เทียบไพ่ที่จั่วได้กับไพ่แต่ละใบในมือ โดยตัวแปร j จะแทนตำแหน่งไพ่แต่ละใบในมือ
for j in range(len(result)):
# ถ้าไพ่ที่จั่วได้มีหน้าไพ่น้อยกว่าหรือเท่ากับไพ่ในมือ
if new_item < result[j]: # แก้ไขโค้ดที่นี่
# ให้แทรกไพ่ที่จั่วได้ลงไปที่ตำแหน่งดังกล่าว แล้วบันทึกไว้ว่าแทรกไพ่ได้แล้ว
result.insert(j, new_item) # แก้ไขโค้ดที่นี่
is_inserted = True
break
# ถ้าหากเทียบจนครบทุกใบในมือแล้ว ยังแทรกไพ่ไม่ได้เลย
if not is_inserted:
# ให้นำไพ่ที่จั่วได้ไปต่อท้ายไพ่ที่อยู่ในมือแทน
result.append(new_item) # แก้ไขโค้ดที่นี่
print(result)
[1, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10]
extend
ลิสต์ปลายทาง.extend(ลิสต์ต้นทาง)
extend
กับ append
ก็คือ extend
จะนำสมาชิกทุกตัวในลิสต์ต้นทางมาต่อท้ายลิสต์ปลายทาง ส่วน append
จะนำสมาชิกหนึ่งตัวมาต่อท้ายลิสต์ครับ[11, 12, 13, 14, 15]
ไปต่อท้ายลิสต์ my_list
ได้ด้วยโปรแกรมนี้ครับmy_list = [1, 2, 3, 4, 5]
new_list = [11, 12, 13, 14, 15]
my_list.extend(new_list)
print(my_list)
[1, 2, 3, 4, 5, 11, 12, 13, 14, 15]
จงนำสมาชิกของลิสต์ new_list_1
, new_list_2
, new_list_3
, และ new_list_4
มาต่อท้ายลิสต์ my_list
เพื่อให้ได้ผลลัพธ์ดังนี้
[10, 11, 12, 4, 5, 6, 7, 8, 9, 1, 2, 3]
my_list = []
new_list_1 = [1, 2, 3]
new_list_2 = [4, 5, 6]
new_list_3 = [7, 8, 9]
new_list_4 = [10, 11, 12]
# ต่อลิสต์ my_list ด้วยคำสั่ง extend
my_list.extend(new_list_4)
my_list.extend(new_list_2)
my_list.extend(new_list_3)
my_list.extend(new_list_1)
print(my_list)
[10, 11, 12, 4, 5, 6, 7, 8, 9, 1, 2, 3]
del
del
ครับmy_numbers
ได้ด้วยคำสั่ง del my_numbers[2]
ดังนี้my_numbers = [11, 12, 13, 14, 15]
del my_numbers[2]
print(my_numbers)
[11, 12, 14, 15]
จงลบสมาชิกออกจากลิสต์ my_numbers
ตามรายการดังต่อไปนี้
แล้วจึงแสดงลิสต์ my_numbers
ออกที่หน้าจอ
my_numbers = [20, 50, 40, 70, 60, 90, 80, 100]
# ลบสมาชิกที่ index 1
del my_numbers[1]
# ลบสมาชิกที่ index 2
del my_numbers[2]
# ลบสมาชิกที่ index 3
del my_numbers[3]
print(my_numbers)
[20, 40, 60, 80, 100]
my_numbers
ได้ดังนี้my_numbers = [11, 12, 13, 14, 15]
del my_numbers[1:4]
print(my_numbers)
[11, 15]
จงลบสมาชิกในช่วง index ที่กำหนดออกจากลิสต์ my_numbers
# สร้างลิสต์จากช่วงจำนวน 0 ถึง 39
my_numbers = list(range(40))
# ลบสมาชิก index ที่ 5 ถึง 10
del my_numbers[5:10]
# ลบสมาชิก index ที่ 15 ถึง 20
del my_numbers[15:20]
print(my_numbers)
[0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]
sort
และ sorted
ลิสต์.sort()
จะเรียงลำดับสมาชิกภายในลิสต์โดยจะทับลิสต์ตัวเดิมไปเลยครับsort
นี้ต่อท้ายลิสต์ที่เราต้องการitems = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
items.sort()
print(items)
[1, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10]
sorted()
จะสร้างลิสต์ใหม่ที่เป็นผลลัพธ์จากการเรียงลำดับสมาชิกในลิสต์ตัวเดิมsorted
คร่อมลิสต์ที่เราต้องการold_items = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
new_items = sorted(old_items)
print('Old items:', old_items)
print('New items:', new_items)
Old items: [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
New items: [1, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10]
reverse=True
ครับitems = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
items.sort(reverse=True)
print(items)
[10, 9, 8, 8, 7, 6, 5, 4, 3, 3, 2, 1]
old_items = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
new_items = sorted(old_items, reverse=True)
print('Old items:', old_items)
print('New items:', new_items)
Old items: [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
New items: [10, 9, 8, 8, 7, 6, 5, 4, 3, 3, 2, 1]
sorted
นี้จะมีประโยชน์มากในการวนลูปตามการเรียงลำดับของสมาชิกภายในลิสต์ โดยที่ไม่ส่งผลข้างเคียงกับลิสต์ดังกล่าวครับitems = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
print('The item list is:', items)
print()
print('Sort and print')
for item in sorted(items):
print('Item =', item)
print()
print('Reversed sort and print')
for item in sorted(items, reverse=True):
print('Item =', item)
print()
print('The item list is still the same:', items)
The item list is: [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
Sort and print
Item = 1
Item = 2
Item = 3
Item = 3
Item = 4
Item = 5
Item = 6
Item = 7
Item = 8
Item = 8
Item = 9
Item = 10
Reversed sort and print
Item = 10
Item = 9
Item = 8
Item = 8
Item = 7
Item = 6
Item = 5
Item = 4
Item = 3
Item = 3
Item = 2
Item = 1
The item list is still the same: [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
จงแสดงความสูงของนักเรียนออกหน้าจอ โดยไล่ลำดับจากหัวแถวซึ่งสูงที่สุด ไปหาท้ายแถวซึ่งเตี้ยที่สุด และแปลงหน่วยของความสูงจากหน่วยเซนติเมตรเป็นหน่วยเมตร ทั้งนี้ขอกำหนดให้ใช้คำสั่ง sorted
ในการจัดลำดับความสูงของนักเรียน
student_heights = [163.5, 150.0, 167.0, 161.25, 170.0]
print([i * 0.01 for i in sorted(student_heights, reverse=True)])
[1.7, 1.67, 1.635, 1.6125, 1.5]
in
'name'
อยู่ในลิสต์ my_list
หรือไม่ เราสามารถใช้คำสั่งว่า 'name' in my_list
ได้ดังตัวอย่างด้านล่างครับmy_list = ['hello', 'my', 'name', 'is', 'prachya']
if 'name' in my_list:
print('It is in the list!')
else:
print('It is not in the list.')
It is in the list!
not in
'doraemon'
อยู่ในลิสต์ my_list
หรือไม่ เราก็ใช้คำสั่ง 'doraemon' not in my_list
ได้ดังตัวอย่างด้านล่างครับmy_list = ['hello', 'my', 'name', 'is', 'prachya']
if 'doraemon' not in my_list:
print('It is not in the list!')
else:
print('It is in the list.')
It is not in the list!
จงนำสมาชิกจากลิสต์ my_list
มาสร้างลิสต์ใหม่ชื่อว่า new_list
โดยลบสมาชิกที่มีซ้ำกันออกไป
my_list = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
new_list = []
for element in my_list:
if element not in new_list:
new_list.append(element)
print(new_list)
[3, 8, 5, 10, 2, 9, 7, 6, 1, 4]
( )
และคั่นด้วยเครื่องหมายคอมมา ,
# คู่ลำดับเป็น tuple ที่มีสมาชิก 2 ตัว
coor1 = (3, 5)
coor2 = (4, 7)
print(coor1)
print(coor2)
# คู่ลำดับสามารถมีสมาชิกได้หลายตัว
my_tuple = (3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4)
print(my_tuple)
(3, 5)
(4, 7)
(3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4)
len
เพื่อหาขนาดของทูเพิลได้len(my_tuple)
12
coor_2d = (3, 5)
coor_3d = (1, 2, 3)
x1, y1 = coor_2d
x2, y2, z2 = coor_3d
print(x1, y1)
print(x2, y2, z2)
3 5
1 2 3
my_tuple[2:7]
(5, 10, 2, 9, 7)
(1, 2, 3) < (1, 2, 4) # ทูเพิลแรกน้อยกว่าทูเพิลหลัง เพราะเปรียบเทียบทีละคู่จนไปเจอว่า 3 < 4
True
(1, 2, 3) < (1, 2, 3, 0) # ทูเพิลแรกน้อยกว่าทูเพิลหลัง เพราะทูเพิลแรกหมดสมาชิกก่อน
True
student_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
for (name, score) in student_scores:
print(name, ':', score)
John : 35.5
Mary : 73.0
Cindy : 83.5
Sean : 65.0
Barry : 81.0
Mark : 79.5
Eugene : 87.0
Bob : 49.5
student_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
student_scores.append( ('Peter', 90.0) ) # โปรดสังเกตว่าจะมีวงเล็บครอบทูเพิลด้วย
student_scores
ซึ่งได้คะแนนสอบมากกว่า 70 คะแนนstudent_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
for (name, score) in student_scores:
if score > 70:
print(name)
Mary
Cindy
Barry
Mark
Eugene
student_scores
โดยเรียงลำดับตามคะแนนจากมากไปหาน้อยstudent_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
inv_scores = []
# กลับลำดับของทูเพิลในลิสต์ student_scores ให้กลายเป็น (คะแนน, ชื่อ) แล้วเก็บลงใน inv_scores
for (nm,sc) in student_scores: # แก้โค้ดที่นี่
inv_scores.append((sc,nm)) # แก้โค้ดที่นี่
# เรียงลำดับข้อมูลใน inv_scores ด้วยคำสั่ง sort โดยเรียงจากมากไปน้อย
inv_scores.sort(reverse=True) # แก้โค้ดที่นี่
# แสดงชื่อและคะแนนของนักเรียนในลิสต์ inv_scores ออกมา
for (score, name) in inv_scores:
print(name, ':', score)
Eugene : 87.0
Cindy : 83.5
Barry : 81.0
Mark : 79.5
Mary : 73.0
Sean : 65.0
Bob : 49.5
John : 35.5
while <เงื่อนไข> :
<กระบวนการ>
items = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
idx = 0
jumping_sum = 0
while idx < len(items) and items[idx] != 7:
print('Adding', items[idx])
jumping_sum = jumping_sum + items[idx]
idx = idx + 2
print('The jumping sum is', jumping_sum)
Adding 3
Adding 5
Adding 2
The jumping sum is 10
break
ครับitems
จากตัวแรกไปเรื่อยๆ จนกว่า จำนวนนั้นจะน้อยกว่าหรือเท่ากับ 2 เราจะเขียนโปรแกรมได้ดังนี้items = [3, 8, 5, 10, 2, 9, 7, 6, 3, 8, 1, 4]
idx = 0
my_sum = 0
while idx < len(items):
print('Adding', items[idx])
my_sum = my_sum + items[idx]
# สังเกตว่าคำสั่ง break จะทำงานหลังจากที่ได้บวกผลรวมเรียบร้อยแล้ว
if items[idx] <= 2:
break
idx = idx + 1
print(my_sum)
Adding 3
Adding 8
Adding 5
Adding 10
Adding 2
28
จงเก็บรวบรวมของตัวเลขจำนวนเต็มทุกตัวที่ผู้ใช้พิมพ์เข้ามาแล้วเรียงลำดับจากมากไปน้อย
ตราบใดที่ผู้ใช้ยังพิมพ์ตัวเลขที่ไม่ใช่เลข 0 เข้ามา ก็ให้รับค่าตัวเลขมาเรื่อยๆ แล้วเก็บไว้ในลิสต์ my_numbers
หากเจอเลข 0 ให้หยุดลูปทันที จากนั้นให้จัดเรียงสมาชิกตามลำดับจากมากไปน้อย แล้วแสดงผลลิสต์นั้นออกมา
my_numbers = []
# วนลูปตลอดไปจนกว่าจะถูกสั่ง break
while True:
num = int(input('Enter an integer: '))
# หากค่า num เป็น 0 ให้ออกจากลูปด้วยคำสั่ง break
if num == 0:
break
# นำค่า num ไปต่อท้ายลิสต์ my_numbers
my_numbers.append(num)
# เรียงลำดับสมาชิกในลิสต์ my_numbers จากมากไปน้อยด้วยคำสั่ง sort
my_numbers.sort()
print(my_numbers)
[1, 2, 5, 5, 5, 5]
while True
จะใช้ในการวนลูปตลอดไป (forever loop) ซึ่งจะมีประโยชน์ในกรณีที่จำเป็นต้องตรวจสอบเงื่อนไขในขณะทำกระบวนการนั่นเองภาษา Python ยังมีโครงสร้างข้อมูลอีกชนิดหนึ่งซึ่งทำหน้าที่เหมือนกับเซ็ตในทางคณิตศาสตร์ โครงสร้างนี้ก็เรียกว่า เซ็ต (set) นั่นเองครับ
เซ็ตจะใช้สัญลักษณ์ { }
สมาชิกแต่ละตัวจะคั่นด้วยเครื่องหมายคอมมา ,
ข้อแตกต่างระหว่างเซ็ตกับลิสต์ก็คือ เซ็ตจะเก็บสมาชิกเฉพาะตัวที่ไม่ซ้ำและไม่จำเป็นว่าจะต้องเรียงลำดับตามการเพิ่มสมาชิก ในขณะที่ลิสต์จะเก็บสมาชิกทุกตัวและเรียงลำดับตามการเพิ่มสมาชิก
my_list = [300, 200, 100, 300, 200]
my_set = {300, 200, 100, 300, 200}
print('This is a list:', my_list)
print('This is a set:', my_set)
This is a list: [300, 200, 100, 300, 200]
This is a set: {200, 100, 300}
for member in my_set:
print(member)
200
100
300
in
print('200 in my_set is', 200 in my_set)
print('400 in my_set is', 400 in my_set)
200 in my_set is True
400 in my_set is False
set()
ได้my_empty_set = set()
print(my_empty_set)
set()
add
และ update
เซ็ต.add(
$e$ )
เมื่อ $e$ คือสมาชิกตัวที่เราจะเพิ่มเข้าไปในเซ็ตเซ็ตปลายทาง.update(ลิสต์หรือเซ็ตต้นทาง)
โดยคำสั่งนี้จะเพิ่มสมาชิกทุกตัวในลิสต์หรือเซ็ตต้นทางเข้าไปในเซ็ตปลายทางนั่นเองmy_set = {300, 200, 100}
print('my_set =', my_set, end='\n\n')
print('Adding 400')
my_set.add(400)
print('my_set =', my_set, end='\n\n')
print('Adding 200')
my_set.add(200)
print('my_set =', my_set, end='\n\n')
print('Updating with [400, 500, 600]')
my_set.update([300, 400, 500, 600])
print('my_set =', my_set)
my_set = {200, 100, 300}
Adding 400
my_set = {200, 100, 300, 400}
Adding 200
my_set = {200, 100, 300, 400}
Updating with [400, 500, 600]
my_set = {100, 200, 300, 400, 500, 600}
จงหาเซ็ตของชื่อนักเรียนจากในรายการคะแนนนักเรียนดังต่อไปนี้
student_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
# สร้างตัวแปร students เพื่อเก็บเซ็ตว่าง
students = [] # แก้โค้ดที่นี่
# ไล่ลูปฟอร์เพื่อเติมชื่อนักเรียนลงในเซ็ต students
for (name, score) in student_scores: # แก้โค้ดที่นี่
students.append(name) # แก้โค้ดที่นี่
print(students)
['John', 'Mary', 'Cindy', 'Sean', 'Barry', 'Mark', 'Eugene', 'Bob']
ตัวดำเนินการ | ภาษา Python | ความหมาย |
---|---|---|
Union (∪) | s1 ⏐ s2 |
นำสมาชิกทั้งสองเซ็ตมารวมกัน |
Intersection (∩) | s1 & s2 |
เลือกสมาชิกที่อยู่ในทั้งสองเซ็ต |
Difference (-) | s1 - s2 |
เลือกเฉพาะสมาชิกที่อยู่ในเซ็ตแรกแต่ไม่อยู่ในเซ็ตสอง |
Symmetric difference (∆) | s1 ^ s2 |
เลือกเฉพาะสมาชิกที่อยู่ในเซ็ตใดเซ็ตหนึ่งเท่านั้น |
Membership (∈) | e in s |
$e$ อยู่ในเซ็ต $s$ หรือไม่ |
Subset (⊆) | s1 <= s2 |
เซ็ต s1 เป็นสับเซ็ตของ s2 หรือไม่ |
Superset (⊇) | s1 >= s2 |
เซ็ต s1 เป็นซูเปอร์เซ็ตของ s2 หรือไม่ |
=
ออกไปได้ครับs1 = {1, 2, 3 }
s2 = { 2, 3, 4}
print('s1 =', s1)
print('s2 =', s2, end='\n\n')
print('Union: s1 ∪ s2 =', s1 | s2)
print('Intersection: s1 ∩ s2 =', s1 & s2)
print('Difference: s1 - s2 =', s1 - s2)
print(' s2 - s1 =', s2 - s1)
print('Symmetric difference: s1 ∆ s2 =', s1 ^ s2)
print('Membership: 3 ∈ s1 =', 3 in s1)
print('Subset: {2, 3} ⊆ s1 =', {2, 3} <= s1)
print(' {1, 2, 3} ⊆ s1 =', {1, 2, 3} <= s1)
print('Pure subset: {2, 3} ⊂ s1 =', {2, 3} < s1)
print(' {1, 2, 3} ⊂ s1 =', {1, 2, 3} < s1)
print('Superset: s1 ⊇ {2, 3} =', s1 >= {2, 3})
print(' s1 ⊇ {1, 2, 3} =', s1 >= {1, 2, 3})
print('Pure superset: s1 ⊃ {2, 3} =', s1 > {2, 3})
print(' s1 ⊃ {1, 2, 3} =', s1 > {1, 2, 3})
s1 = {1, 2, 3}
s2 = {2, 3, 4}
Union: s1 ∪ s2 = {1, 2, 3, 4}
Intersection: s1 ∩ s2 = {2, 3}
Difference: s1 - s2 = {1}
s2 - s1 = {4}
Symmetric difference: s1 ∆ s2 = {1, 4}
Membership: 3 ∈ s1 = True
Subset: {2, 3} ⊆ s1 = True
{1, 2, 3} ⊆ s1 = True
Pure subset: {2, 3} ⊂ s1 = True
{1, 2, 3} ⊂ s1 = False
Superset: s1 ⊇ {2, 3} = True
s1 ⊇ {1, 2, 3} = True
Pure superset: s1 ⊃ {2, 3} = True
s1 ⊃ {1, 2, 3} = False
จงเขียนโปรแกรมเพื่อหาเซ็ตของนักเรียนที่มีคุณสมบัติดังต่อไปนี้
เซ็ตของชื่อนักเรียนยอดเยี่ยม excellent_students
ซึ่งจะมีคะแนนตั้งแต่ 80 คะแนนขึ้นไป
เซ็ตของชื่อนักเรียนเรียนดี good_students
ซึ่งมีคะแนนตั้งแต่ 70 คะแนนจนถึง 85 คะแนน
หลังจากนั้นให้คำนวณเซ็ตดังต่อไปนี้
นักเรียนที่เป็นทั้งยอดเยี่ยม**และ**เรียนดีในเวลาเดียวกัน คือจะเป็นเฉพาะยอดเยี่ยมหรือเรียนดีอย่างเดียวไม่ได้
นักเรียนที่เป็นยอดเยี่ยม**เท่านั้น** ไม่ได้เป็นเรียนดี
นักเรียนที่เป็นเรียนดี**เท่านั้น** ไม่ได้เป็นยอดเยี่ยม
นักเรียนที่ได้เป็นยอดเยี่ยมหรือได้เป็นเรียนดี **อย่างใดอย่างหนึ่งเท่านั้น**
student_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5), ('Sean', 65.0),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Bob', 49.5)
]
# เซ็ตของชื่อนักเรียนยอดเยี่ยม
excellent_students = set()
# เซ็ตของชื่อนักเรียนเรียนดี
good_students = set()
for (name, score) in student_scores:
# กรณีนักเรียนยอดเยี่ยม ให้นำเฉพาะชื่อนักเรียนใส่เซ็ต excellent_students ไว้
if score >= 80:
excellent_students.add(name)
# กรณีนักเรียนเรียนดี ให้นำเฉพาะชื่อนักเรียนใส่เซ็ต good_students ไว้
if score >= 70 and score < 85:
good_students.add(name)
print('นักเรียนยอดเยี่ยม:', excellent_students)
print('นักเรียนเรียนดี:', good_students, end='\n\n')
print('นักเรียนยอดเยี่ยมและเรียนดี:', excellent_students & good_students)
print('นักเรียนยอดเยี่ยมแต่ไม่ได้เรียนดี:', excellent_students - good_students)
print('นักเรียนเรียนดีแต่ไม่ได้ยอดเยี่ยม:', good_students - excellent_students)
print('นักเรียนเรียนดีหรือยอดเยี่ยม อย่างใดอย่างหนึ่ง:', excellent_students ^ good_students)
นักเรียนยอดเยี่ยม: {'Cindy', 'Eugene', 'Barry'}
นักเรียนเรียนดี: {'Mark', 'Cindy', 'Mary', 'Barry'}
นักเรียนยอดเยี่ยมและเรียนดี: {'Cindy', 'Barry'}
นักเรียนยอดเยี่ยมแต่ไม่ได้เรียนดี: {'Eugene'}
นักเรียนเรียนดีแต่ไม่ได้ยอดเยี่ยม: {'Mark', 'Mary'}
นักเรียนเรียนดีหรือยอดเยี่ยม อย่างใดอย่างหนึ่ง: {'Mary', 'Eugene', 'Mark'}
ดิกชันนารี (dictionary) คือโครงสร้างข้อมูลที่เชื่อมโยงคีย์ (key) ไปยังค่า (value) ที่เก็บเอาไว้ในคีย์นั้น
คีย์ของดิกชันนารีอาจจะเป็นตัวเลข สตริง หรือแม้แต่ทูเพิลก็ได้ และค่าที่เก็บไว้ในคีย์นั้นจะเป็นชนิดใดก็ได้
ดิกชันนารีแตกต่างจากลิสต์และทูเพิลตรงที่
{}
{
$k_1$ :
$v_1$ ,
$k_2$ :
$v_2$ ,
$k_3$ :
$v_3$ ,
… }
โดยจะมีคู่ของคีย์ $k_i$ และค่า $v_i$ เรียงกันไป คั่นด้วยเครื่องหมายคอมมา ,
# ดิกชันนารีเปล่า
my_empty_dict = {}
# ดิกชันนารีที่มีค่าเริ่มต้น
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
print(my_empty_dict)
print(student_dict)
{}
{'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0, 'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5}
จงสร้างดิกชันนารี phone_dir
ซึ่งมีค่าเริ่มต้นดังต่อไปนี้
'Prachya'
มีค่า '533-7855'
'Methas'
มีค่า '536-2313'
'Pahol'
มีค่า '524-0935'
phone_dir = {
"Prachya": '533-7855',
"Methas": '536-2313',
"Pahol": '524-0935'
}
จงเขียนโปรแกรมรับชื่อและเบอร์โทรศัพท์จากผู้ใช้ หลังจากนั้นให้สร้างดิกชันนารี phone_entry
ที่มีโครงสร้างดังนี้
'first_name'
เก็บชื่อ'last_name'
เก็บนามสกุล'tel_no'
เก็บเบอร์โทรศัพท์หลังจากนั้นจึงแสดงดิกชันนารีนี้ออกทางหน้าจอ
first_name = input('Enter first name: ')
last_name = input('Enter last name: ')
tel_no = input('Enter tel no: ')
phone_entry = { 'first_name': first_name, 'last_name': last_name, 'tel_no': last_name } # แก้ไขโค้ดที่นี่
print(phone_entry)
{'first_name': 'Jane', 'last_name': 'Smith', 'tel_no': 'Smith'}
จงเขียนโปรแกรมทยอยรับชื่อและเบอร์โทรศัพท์จากผู้ใช้ สร้างดิกชันนารี phone_entry
ที่มีโครงสร้างดังนี้
'first_name'
เก็บชื่อ'last_name'
เก็บนามสกุล'tel_no'
เก็บเบอร์โทรศัพท์แล้วนำดิกชันนารีนี้ไปต่อท้ายในลิสต์ phone_database
ซึ่งเก็บฐานข้อมูลของผู้ใช้โทรศัพท์
โปรแกรมนี้จะหยุดรับค่าจากผู้ใช้หากว่า ชื่อ นามสกุล หรือเบอร์โทรศัพท์ที่รับมาจากผู้ใช้ เป็นสตริงว่าง
เมื่อโปรแกรมหยุดรับค่าจากผู้ใช้ ให้โปรแกรมไล่แสดงผลดิกชันนารีที่เก็บในลิสต์ phone_database
ออกมาทีละอันจนกว่าจะหมด
# ลิสต์สำหรับฐานข้อมูลผู้ใช้โทรศัพท์
phone_database = []
# วนลูปตลอดไป
while True:
# รับชื่อ นามสกุล และเบอร์โทรศัพท์จากผู้ใช้
first_name = input('Enter first name: ')
last_name = input('Enter last name: ')
tel_no = input('Enter tel no: ')
# ถ้าหากชื่อ นามสกุล หรือเบอร์โทรศัพท์เป็นสตริงว่าง ให้หยุดการทำงานของลูปนี้ด้วย break
if first_name == '' or last_name == '':
break
# นำชื่อ นามสกุล และเบอร์โทรศัพท์ มาสร้างดิกชันนารี
phone_entry = { 'fn': first_name, 'ln': last_name } # แก้ไขโค้ดที่นี่
# นำดิกชันนารีนี้ไปต่อท้าย phone_database
phone_database.append(phone_entry) # แก้ไขโค้ดที่นี่
# แสดงผลดิกชันนารีใน phone_database ทีละอัน
for entry in phone_database:
print(f"Name: {entry['fn']} {entry['ln']}") # แก้ไขโค้ดที่นี่
Name: John Smith
[ ]
เหมือนกับลิสต์และทูเพิลเลยครับstudent_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
print(student_dict['Mary'])
print(student_dict['Eugene'])
73.0
87.0
KeyError
ซึ่งแปลว่า หาคีย์ไม่เจอ นั่นเองครับprint(student_dict['Lucy'])
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
/tmp/ipykernel_4316/1927303255.py in <module>
----> 1 print(student_dict['Lucy'])
KeyError: 'Lucy'
ดังนั้นเพื่อป้องกันไม่ให้เกิดเหตุการณ์แบบนี้ เราจึงจำเป็นต้องตรวจสอบความเป็นสมาชิกของคีย์เสียก่อน
เราสามารถตรวจสอบความเป็นสมาชิกของคีย์ในดิกชันนารีได้ด้วยคำสั่ง in
ครับ
print('Lucy' in student_dict)
print('Mary' in student_dict)
False
True
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
student_dict['Rupert'] = 91.0
print(student_dict)
{'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0, 'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5, 'Rupert': 91.0}
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
student_dict['Mary'] = 89.0
student_dict['Barry'] = student_dict['Barry'] + 5
print(student_dict)
{'John': 35.5, 'Mary': 89.0, 'Cindy': 83.5, 'Sean': 65.0, 'Barry': 86.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5}
จงเขียนโปรแกรมเพื่อเก็บคะแนนสอบของนักเรียนลงในดิกชันนารี student_dict
โดยโปรแกรมจะถามหาชื่อของนักเรียน
หากชื่อนั้นมีอยู่ใน student_dict
อยู่แล้ว ก็ให้แสดงคะแนนที่เคยกรอกไว้แล้วออกมา
ไม่เช่นนั้นก็ให้คอมพิวเตอร์ถามคะแนนจากผู้ใช้เป็นจำนวนจริง (แปลงด้วยคำสั่ง float
) แล้วเก็บลงในดิกชันนารีดังกล่าว
โปรแกรมจะถามหาชื่อนักเรียนไปเรื่อยๆ จนกว่าผู้ใช้จะกรอกสตริงว่างลงในชื่อของนักเรียน จนจะหยุดการทำงานของโปรแกรม
สุดท้ายโปรแกรมจะแสดงดิกชันนารี student_dict
ออกทางหน้าจอ
# ดิกชันนารีเก็บคะแนนสอบของนักเรียน
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
# วนลูปตลอดไป
while True:
# รับชื่อนักเรียนจากผู้ใช้
name = input('Enter student name: ')
# ถ้าชื่อเป็นสตริงว่าง ให้หยุดการทำงานด้วยคำสั่ง break
if name == '':
break # แก้ไขโค้ดที่นี่
# ถ้าหากชื่อของนักเรียนมีอยู่ใน student_dict อยู่แล้ว
if name in student_dict:
# ให้แสดงคะแนนของนักเรียนคนนั้นออกทางหน้าจอ
print('Score =', student_dict[name] ) # แก้ไขโค้ดที่นี่
# ไม่เช่นนั้น
else:
# รับค่าคะแนนจากผู้ใช้
score = float(input('Enter score: '))
# บันทึกคะแนนของนักเรียน โดยใช้ name เป็นคีย์ในการบันทึกลงในดิกชันนารี
student_dict[name] = score # แก้ไขโค้ดที่นี่
# print()
print(student_dict)
Score = 73.0
Score = 79.5
{'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0, 'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5}
del
ครับstudent_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
del student_dict['Barry']
print(student_dict)
{'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5}
เราสามารถวนลูปบนดิกชันนารีได้ 2 วิธี
**วิธีที่ 1:** ใช้ลูปฟอร์ ซึ่งจะวนลูปทุกๆ คีย์ในดิกชันนารีนั้น
for <คีย์> in <ดิกชันนารี> :
<กระบวนการ>
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
for name in student_dict:
print(name, ':', student_dict[name])
John : 35.5
Mary : 73.0
Cindy : 83.5
Sean : 65.0
Barry : 81.0
Mark : 79.5
Eugene : 87.0
Bob : 49.5
sorted
ได้อีกด้วยครับstudent_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
for name in sorted(student_dict):
print(name, ':', student_dict[name])
Barry : 81.0
Bob : 49.5
Cindy : 83.5
Eugene : 87.0
John : 35.5
Mark : 79.5
Mary : 73.0
Sean : 65.0
ดิกชันนารี.items()
ซึ่งวิธีหลังนี้จะประหยัดเวลากว่า ถ้าหากเราอยากใช้ทั้งคีย์และค่าในคีย์ในกระบวนการนั้นครับ
for <คีย์>, <ค่าในคีย์> in <ดิกชันนารี>.items():
<กระบวนการ>
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
for name, score in student_dict.items():
print(name, ':', score)
John : 35.5
Mary : 73.0
Cindy : 83.5
Sean : 65.0
Barry : 81.0
Mark : 79.5
Eugene : 87.0
Bob : 49.5
**คำเตือน**: ในขณะที่ทำลูปฟอร์ ห้ามเพิ่มหรือลบคีย์ในดิกชันนารีโดยเด็ดขาด เพราะลูปฟอร์จะบังคับให้ดิกชันนารีต้องมีขนาดคงที่เสมอ
เช่น ถ้ารันโปรแกรมด้านล่างนี้ เครื่องจะฟ้องว่าขนาดของดิกชันนารีมีการเปลี่ยนแปลงในลูปฟอร์นั่นเอง
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
for name in student_dict:
del student_dict[name]
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
/tmp/ipykernel_4316/4054559271.py in <module>
4 }
5
----> 6 for name in student_dict:
7 del student_dict[name]
RuntimeError: dictionary changed size during iteration
จงเขียนโปรแกรมเพื่อแจ้งว่า นักเรียนคนใดในดิกชันนารี student_dict
อยู่ในภาวะน่าเป็นห่วง (probation) โดยจะมีคะแนนน้อยกว่า 50 คะแนน และให้โปรแกรมเรียงลำดับชื่อตามตัวอักษรด้วย
# ดิกชันนารีเก็บคะแนนสอบของนักเรียน
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
# ใช้ลูปฟอร์ไล่คีย์และค่าในคีย์ โดยเรียงลำดับชื่อตามตัวอักษร
for name in sorted(student_dict):
# ถ้าหากคะแนนต่ำกว่า 50 คะแนน แสดงว่าอยู่ในภาวะน่าเป็นห่วง
if student_dict[name] < 50:
print( name , 'is on probation.')
Bob is on probation.
John is on probation.
จงเขียนโปรแกรมให้รับชื่อของนักเรียน หากชื่อของนักเรียนปรากฏอยู่ในดิกชันนารี student_dict
ให้นับจำนวนมาว่า มีนักเรียนกี่คนที่มีคะแนนน้อยกว่านักเรียนคนนี้ แต่ถ้าหากไม่มี ให้ตอบว่ามี 0 คน
# ดิกชันนารีเก็บคะแนนสอบของนักเรียน
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
# ชื่อนักเรียน
name = input('Enter student name: ')
# ตัวนับจำนวนนักเรียนที่มีคะแนนน้อยกว่า
count = 0
# หากมีชื่อนักเรียนคนนี้ในดิกชันนารี student_dict
if name in student_dict:
# ให้วนลูปฟอร์นักเรียนที่มีใน student_dict
for index in student_dict: # แก้ไขโค้ดที่นี่
# ถ้าหากคะแนนต่ำกว่าคะแนนของนักเรียนที่ผู้ใช้ระบุ
if student_dict[index] < student_dict[name]: # แก้ไขโค้ดที่นี่
count = count + 1
print('Number of students with lower score =', count)
Number of students with lower score = 0
ที่จริงแล้วเราสามารถจัดรูปแบบของสตริงก่อนที่จะแสดงผลได้ครับ
วิธีการคือ เราจะใช้สัญลักษณ์ f
นำหน้าสตริงที่เราต้องการจะให้จัดรูปแบบ ซึ่งสัญลักษณ์ f
ย่อมาจากคำว่า format (รูปแบบ) นั่นเอง
ข้อดีของการใช้สัญลักษณ์ f
นำหน้าสตริงก็คือ เราสามารถแทรกค่าตัวแปรลงไปตำแหน่งใดของสตริงก็ได้ เพียงแค่ครอบตัวแปรด้วยปีกกา { }
เท่านั้น นับว่าสะดวกมากครับ
name = 'Prachya'
telno = '533-7855'
age = 37
degree = 'high-school'
print(f'My name is {name} and I am {age} years old. I am still a {degree} student and my phone number is {telno}.')
My name is Prachya and I am 37 years old. I am still a high-school student and my phone number is 533-7855.
ในกรณีของสตริง เราสามารถระบุความกว้างสูงสุดของสตริงได้ด้วยคำสั่ง {ตัวแปรสตริง:ความกว้าง}
โดยสตริงจะถูกแสดงผลแบบชิดซ้าย
การกำหนดความกว้างของสตริงได้ ทำให้เราสามารถพิมพ์ตารางออกมาได้สะดวกมากครับ โดยจะจัดชิดซ้ายเสมอครับ
user_database = [
('Prachya', '533-7855', 37, 'high-school'),
('Methas', '536-2313', 36, 'university'),
('Pahol', '524-0935', 38, 'university')
]
print(60 * '-')
for name, telno, age, degree in user_database:
print(f'| {name:20} | {telno:15} | {degree:15} |')
print(60 * '-')
------------------------------------------------------------
| Prachya | 533-7855 | high-school |
| Methas | 536-2313 | university |
| Pahol | 524-0935 | university |
------------------------------------------------------------
<
, ^
, และ >
ที่ด้านหน้าความกว้างของสตริงครับprint(60 * '-')
for name, telno, age, degree in user_database:
print(f'| {name:<15} | {telno:^15} | {degree:>15} |')
print(60 * '-')
------------------------------------------------------------
| Prachya | 533-7855 | high-school |
| Methas | 536-2313 | university |
| Pahol | 524-0935 | university |
------------------------------------------------------------
จงแสดงตารางการจัดคู่เปรียบเทียบคะแนนของนักเรียนแต่ละคน โดยกำหนดฟอร์แมตไว้ดังนี้
--DUE--
แบบจัดกลาง ลงในช่องของชื่อผู้ชนะแทนstudent_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Rupert', 81.0)
]
# พิมพ์หัวตาราง
print(42 * '-')
print(f'| {"Score Battles":^25} | {"Winners":^10} |')
print(42 * '-')
for student1, score1 in student_scores:
for student2, score2 in student_scores:
if student1 != student2:
# พิมพ์ชื่อของนักเรียนคนที่ 1 (student1) และนักเรียนคนที่ 2 (student2)
print(f'| {student1:>10} vs. {student2:<10} ', end='')
# หาผู้ชนะคะแนน แล้วพิมพ์ชื่อผู้ชนะออกมา
if score1 > score2:
print(f'| {student1:^10} |')
elif score1 < score2:
print(f'| {student2:^10} |')
# กรณีที่คะแนนเสมอกัน
else:
print(f'| {"--DUE--":^10} |')
print(42 * '-')
------------------------------------------
| Score Battles | Winners |
------------------------------------------
| John vs. Mary | Mary |
| John vs. Cindy | Cindy |
| John vs. Barry | Barry |
| John vs. Mark | Mark |
| John vs. Eugene | Eugene |
| John vs. Rupert | Rupert |
------------------------------------------
| Mary vs. John | Mary |
| Mary vs. Cindy | Cindy |
| Mary vs. Barry | Barry |
| Mary vs. Mark | Mark |
| Mary vs. Eugene | Eugene |
| Mary vs. Rupert | Rupert |
------------------------------------------
| Cindy vs. John | Cindy |
| Cindy vs. Mary | Cindy |
| Cindy vs. Barry | Cindy |
| Cindy vs. Mark | Cindy |
| Cindy vs. Eugene | Eugene |
| Cindy vs. Rupert | Cindy |
------------------------------------------
| Barry vs. John | Barry |
| Barry vs. Mary | Barry |
| Barry vs. Cindy | Cindy |
| Barry vs. Mark | Barry |
| Barry vs. Eugene | Eugene |
| Barry vs. Rupert | --DUE-- |
------------------------------------------
| Mark vs. John | Mark |
| Mark vs. Mary | Mark |
| Mark vs. Cindy | Cindy |
| Mark vs. Barry | Barry |
| Mark vs. Eugene | Eugene |
| Mark vs. Rupert | Rupert |
------------------------------------------
| Eugene vs. John | Eugene |
| Eugene vs. Mary | Eugene |
| Eugene vs. Cindy | Eugene |
| Eugene vs. Barry | Eugene |
| Eugene vs. Mark | Eugene |
| Eugene vs. Rupert | Eugene |
------------------------------------------
| Rupert vs. John | Rupert |
| Rupert vs. Mary | Rupert |
| Rupert vs. Cindy | Cindy |
| Rupert vs. Barry | --DUE-- |
| Rupert vs. Mark | Rupert |
| Rupert vs. Eugene | Eugene |
------------------------------------------
หากกรณีที่ค่าที่เราจะแสดงเป็นค่าที่ต้องเข้าถึงด้วยคีย์หรือ index เราก็สามารถใช้เครื่องหมาย indexing [ ]
ได้ตามปกติเลยครับ
อย่างไรก็ตามโปรดสังเกตว่า หากคีย์ที่ใช้จำเป็นต้องมีเครื่องหมายคำพูดเดี่ยว (single quote) ให้เราเปลี่ยนเครื่องหมายนั้นเป็นเครื่องหมายคำพูดคู่ (double quote) " "
แทนนะครับ ไม่งั้นเดี๋ยวจะซ้ำกับเครื่องหมายคำพูดเดี่ยวที่ครอบอยู่ด้านนอก คอมพิวเตอร์จะงงเอาได้ครับ
user_database = [
{'name': 'Prachya', 'telno': '533-7855', 'age': 37, 'degree': 'high-school'},
{'name': 'Methas', 'telno': '536-2313', 'age': 36, 'degree': 'university'},
{'name': 'Pahol', 'telno': '524-0935', 'age': 38, 'degree': 'university'}
]
print(60 * '-')
for user in user_database:
print(f'| {user["name"]:<20} | {user["telno"]:^15} | {user["degree"]:>15} |')
print(60 * '-')
------------------------------------------------------------
| Prachya | 533-7855 | high-school |
| Methas | 536-2313 | university |
| Pahol | 524-0935 | university |
------------------------------------------------------------
d
ตามหลังตัวเลขf
ตามหลังตัวเลขuser['age']
มีความกว้าง 3 ตัวอักษรและชิดขวาได้ดังนี้ครับuser_database = [
{'name': 'Prachya', 'telno': '533-7855', 'age': 37, 'degree': 'high-school'},
{'name': 'Methas', 'telno': '536-2313', 'age': 36, 'degree': 'university'},
{'name': 'Pahol', 'telno': '524-0935', 'age': 38, 'degree': 'university'}
]
print(66 * '-')
for user in user_database:
print(f'| {user["name"]:<20} | {user["telno"]:^15} | {user["age"]:>3d} | {user["degree"]:>15} |')
print(66 * '-')
------------------------------------------------------------------
| Prachya | 533-7855 | 37 | high-school |
| Methas | 536-2313 | 36 | university |
| Pahol | 524-0935 | 38 | university |
------------------------------------------------------------------
ในกรณีที่เป็นตัวเลขจำนวนจริง เราสามารถระบุได้ทั้งความกว้างและจำนวนหลักทศนิยม โดยใช้รูปแบบเป็น ความกว้าง.จำนวนหลักทศนิยมf
**ข้อควรระวัง:** ความกว้างตรงนี้เป็นความกว้างทั้งหมด ซึ่งรวมเอาจุดทศนิยมและหลักทศนิยมเข้าไปแล้ว ท่านจึงควรระมัดระวังตอนกำหนดความกว้างทั้งหมดให้ดีนะครับ
เช่น เราสามารถแสดงคะแนนของนักเรียน score
ให้มีความกว้าง 8 ตัวอักษร และมีทศนิยม 2 ตำแหน่งได้โดยใช้ฟอร์แมต {score:8.2f}
student_dict = {
'John': 35.5, 'Mary': 73.0, 'Cindy': 83.5, 'Sean': 65.0,
'Barry': 81.0, 'Mark': 79.5, 'Eugene': 87.0, 'Bob': 49.5
}
print(35 * '-')
for name, score in student_dict.items():
print(f'| {name:<20} | {score:>8.2f} |')
print(35 * '-')
-----------------------------------
| John | 35.50 |
| Mary | 73.00 |
| Cindy | 83.50 |
| Sean | 65.00 |
| Barry | 81.00 |
| Mark | 79.50 |
| Eugene | 87.00 |
| Bob | 49.50 |
-----------------------------------
ก็อปปี้บางส่วนของโปรแกรมในแบบฝึกหัด 13.1 มาแก้ไข โดยเพิ่มอีก 1 คอลัมน์เข้าไปในตาราง
student_scores = [
('John', 35.5), ('Mary', 73.0), ('Cindy', 83.5),
('Barry', 81.0), ('Mark', 79.5), ('Eugene', 87.0), ('Rupert', 81.0)
]
# พิมพ์หัวตาราง
print(53 * '-')
print(f'| {"Score Battles":^25} | {"Winners":^10} | {"Diff":>8} |')
print(53 * '-')
for student1, score1 in student_scores:
for student2, score2 in student_scores:
if student1 != student2:
# พิมพ์ชื่อของนักเรียนคนที่ 1 (student1) และนักเรียนคนที่ 2 (student2)
print(f'| {student1:>10} vs. {student2:<10} ', end='')
# หาผู้ชนะคะแนน แล้วพิมพ์ชื่อผู้ชนะออกมา
if score1 > score2:
score_diff = score1 - score2
print(f'| {student1:^10} ', end='')
elif score1 < score2:
score_diff = score2 - score1
print(f'| {student2:^10} ', end='')
# กรณีที่คะแนนเสมอกัน
else:
score_diff = 0
print(f'| {"--DUE--":^10} ', end='')
# พิมพ์ผลต่างของคะแนน score_diff หรือไม่ก็เว้นว่างหากเป็น 0
if score_diff > 0.0:
print(f'| {score_diff:8.2f} |')
else:
print('| |')
print(53 * '-')
-----------------------------------------------------
| Score Battles | Winners | Diff |
-----------------------------------------------------
| John vs. Mary | Mary | 37.50 |
| John vs. Cindy | Cindy | 48.00 |
| John vs. Barry | Barry | 45.50 |
| John vs. Mark | Mark | 44.00 |
| John vs. Eugene | Eugene | 51.50 |
| John vs. Rupert | Rupert | 45.50 |
-----------------------------------------------------
| Mary vs. John | Mary | 37.50 |
| Mary vs. Cindy | Cindy | 10.50 |
| Mary vs. Barry | Barry | 8.00 |
| Mary vs. Mark | Mark | 6.50 |
| Mary vs. Eugene | Eugene | 14.00 |
| Mary vs. Rupert | Rupert | 8.00 |
-----------------------------------------------------
| Cindy vs. John | Cindy | 48.00 |
| Cindy vs. Mary | Cindy | 10.50 |
| Cindy vs. Barry | Cindy | 2.50 |
| Cindy vs. Mark | Cindy | 4.00 |
| Cindy vs. Eugene | Eugene | 3.50 |
| Cindy vs. Rupert | Cindy | 2.50 |
-----------------------------------------------------
| Barry vs. John | Barry | 45.50 |
| Barry vs. Mary | Barry | 8.00 |
| Barry vs. Cindy | Cindy | 2.50 |
| Barry vs. Mark | Barry | 1.50 |
| Barry vs. Eugene | Eugene | 6.00 |
| Barry vs. Rupert | --DUE-- | |
-----------------------------------------------------
| Mark vs. John | Mark | 44.00 |
| Mark vs. Mary | Mark | 6.50 |
| Mark vs. Cindy | Cindy | 4.00 |
| Mark vs. Barry | Barry | 1.50 |
| Mark vs. Eugene | Eugene | 7.50 |
| Mark vs. Rupert | Rupert | 1.50 |
-----------------------------------------------------
| Eugene vs. John | Eugene | 51.50 |
| Eugene vs. Mary | Eugene | 14.00 |
| Eugene vs. Cindy | Eugene | 3.50 |
| Eugene vs. Barry | Eugene | 6.00 |
| Eugene vs. Mark | Eugene | 7.50 |
| Eugene vs. Rupert | Eugene | 6.00 |
-----------------------------------------------------
| Rupert vs. John | Rupert | 45.50 |
| Rupert vs. Mary | Rupert | 8.00 |
| Rupert vs. Cindy | Cindy | 2.50 |
| Rupert vs. Barry | --DUE-- | |
| Rupert vs. Mark | Rupert | 1.50 |
| Rupert vs. Eugene | Eugene | 6.00 |
-----------------------------------------------------
เราสามารถเปิดไฟล์ได้โดยใช้คำสั่ง open(ชื่อไฟล์, ข้ออนุญาต)
โดยเราจะต้องนำตัวแปร 1 ตัว (ซึ่งเรียกว่า file handler) มารับตัวแทนไฟล์นั้นเอาไว้ เราจะได้นำไฟล์ไปใช้งานต่อได้
'r'
คืออ่านข้อมูลอย่างเดียวเท่านั้น'w'
คือเขียนข้อมูลทับอย่างเดียวเท่านั้น'a'
คือเขียนข้อมูลต่อท้ายอย่างเดียวเท่านั้นไฟล์.close()
ครับfhdl = open('test_file_1.txt', 'w') # fhdl ย่อมาจากคำว่า file handler
fhdl.close()
ไฟล์.write(สตริง)
\n
เองด้วยfhdl = open('test_file_1.txt', 'w')
for i in range(1, 11):
fhdl.write(f'{10 * i}\n')
fhdl.close()
for <บรรทัด> in <ไฟล์> :
<กระบวนการ>
\n
ติดมาด้วยเสมอfhdl = open('test_file_1.txt', 'r')
for line in fhdl:
print(line)
fhdl.close()
10
20
30
40
50
60
70
80
90
100
ดังนั้นปกติแล้ว เราจะสั่ง สตริง.strip()
แต่ละบรรทัดด้วย เพื่อกำจัดเครื่องหมายเว้นวรรคและขึ้นบรรทัดใหม่ที่ด้านซ้ายและขวาออกไปครับ
เช่น ถ้าเราต้องการจะอ่านตัวเลขในไฟล์ test_file_1.txt
ออกมาแล้วหาผลรวม เราจะเขียนโปรแกรมได้ดังนี้
fhdl = open('test_file_1.txt', 'r')
my_sum = 0
for line in fhdl:
numstr = line.strip() # กำจัดเว้นวรรคและขึ้นบรรทัดใหม่ซ้ายขวาทิ้งไป
my_sum = my_sum + int(numstr)
fhdl.close()
print(my_sum)
550
นอกจากนี้เรายังสามารถอ่านไฟล์ทุกบรรทัดได้ในคราวเดียวด้วยคำสั่ง ไฟล์.readlines()
strip()
เช่นเคยfhdl = open('test_file_1.txt', 'r')
lines = fhdl.readlines()
fhdl.close()
print(lines)
for i in range(len(lines)):
lines[i] = lines[i].strip()
print(lines)
['10\n', '20\n', '30\n', '40\n', '50\n', '60\n', '70\n', '80\n', '90\n', '100\n']
['10', '20', '30', '40', '50', '60', '70', '80', '90', '100']
จงอ่านข้อมูลจากไฟล์ test_file_1.txt
แล้วเขียนข้อมูลลงไปในไฟล์ test_file_2.txt
โดยจะต้องกลับลำดับการเขียนด้วย ดังนั้นในไฟล์ test_file_2.txt
จะต้องมีข้อมูลที่สลับลำดับบรรทัดกับไฟล์ test_file_1.txt
ที่เป็นอินพุต
# เปิดไฟล์ test_file_1.txt แบบอ่านอย่างเดียว
ifhdl = open('test_file_1.txt', 'r')
# อ่านทุกบรรทัดของไฟล์ ifhdl ใส่ตัวแปร lines
lines = ifhdl.readlines()
# ปิดไฟล์ทันทีที่ใช้เสร็จ
ifhdl.close()
# กลับลำดับของสมาชิกในลิสต์ lines
lines.reverse()
# เปิดไฟล์ test_file_2.txt แบบเขียนทับอย่างเดียว
ofhdl = open('test_file_2.txt', 'w')
# วนลูปตามบรรทัด
for i in range(len(lines)):
# เขียนบรรทัดดังกล่าวลงในไฟล์ ofhdl
ofhdl.write(lines[i])
# ปิดไฟล์ทันทีที่ใช้เสร็จ
ofhdl.close()
สตริง.split()
ครับtokens = 'hello this is prachya and i am glad to be here'.split()
print(tokens)
['hello', 'this', 'is', 'prachya', 'and', 'i', 'am', 'glad', 'to', 'be', 'here']
split()
ก็ยังสามารถแบ่งสตริงออกเป็นลิสต์ของคำได้tokens = ' hello this is prachya and i am glad to be here '.split()
print(tokens)
['hello', 'this', 'is', 'prachya', 'and', 'i', 'am', 'glad', 'to', 'be', 'here']
,
เราจะใช้คำสั่งดังนี้ครับtokens = '533-7855,536-2313,524-7306'.split(',')
print(tokens)
['533-7855', '536-2313', '524-7306']
split()
จะยอมปล่อยให้มีสตริงว่างเกิดขึ้นได้ด้วย หากว่ามีเครื่องหมายตัดสตริงปรากฏขึ้นติดกันหลายครั้งtokens = '533-7855,,536-2313,,,,524-7306'.split(',')
print(tokens)
['533-7855', '', '536-2313', '', '', '', '524-7306']
สตริงเชื่อม.join(ลิสต์ของสตริง)
ครับwords = ['hello', 'this', 'is', 'prachya', 'and', 'i', 'am', 'glad', 'to', 'be', 'here']
print(' '.join(words))
hello this is prachya and i am glad to be here
words = ['hello', 'this', 'is', 'prachya', 'and', 'i', 'am', 'glad', 'to', 'be', 'here']
print(''.join(words))
hellothisisprachyaandiamgladtobehere
สตริง.strip()
text = ' In the beginning, there was darkness. '
print(f'|{text}|')
print(f'|{text.strip()}|')
| In the beginning, there was darkness. |
|In the beginning, there was darkness.|
คำสั่งนี้จะมีประโยชน์มาก เวลาที่เราแตกสตริง แล้วนำแต่ละคำที่ได้มาแปลงเป็นตัวเลข ในกรณีนี้เราต้องกำจัดช่องว่างซ้ายขวาด้วย strip()
ก่อนเสมอ ไม่เช่นนั้นเราจะไม่สามารถแปลงแต่ละคำเป็นตัวเลขได้เลย
เช่น เราจะหาผลรวมของตัวเลขจำนวนเต็มที่อยู่ในสตริง number_text
number_text = ' 10 , 20 , 30 , 40 , 50 '
tokens = number_text.split(',')
my_sum = 0
for token in tokens:
num = token.strip()
my_sum = my_sum + int(num)
print(my_sum)
150
จงรับตัวเลข 1 ตัวจากผู้ใช้ แล้วสร้างไฟล์ test_file_3.txt
ดังตัวอย่างต่อไปนี้
Enter n: 5
ส่วนตรงนี้คือเนื้อหาของไฟล์ที่ได้จากค่าอินพุต n
50 40 30 20 10
40 30 20 10
30 20 10
20 10
10
โดยตัวเลขทุกตัวจะต้องมีความกว้าง 10 ตัวอักษรชิดซ้าย
n = 5 or int(input('Enter n: '))
ofhdl = open('test_file_3.txt', 'w')
for i in range(n, 0, -1):
for j in range(i, 0, -1):
ofhdl.write(f'{j*10:<10}')
ofhdl.write('\n')
ofhdl.close()
ท่านสามารถตรวจสอบผลลัพธ์ได้จากการรันโปรแกรมด้านล่างนี้
ifhdl = open('test_file_3.txt', 'r')
for line in ifhdl:
print(line.strip())
ifhdl.close()
50 40 30 20 10
40 30 20 10
30 20 10
20 10
10
จงอ่านไฟล์ test_file_3.txt
จากแบบฝึกหัด 14.2 แล้วหาผลรวมของตัวเลขในแต่ละบรรทัด เช่น ถ้าไฟล์ test_file_3.txt
มีเนื้อหาเป็นดังนี้
50 40 30 20 10
40 30 20 10
30 20 10
20 10
10
เราจะได้ผลลัพธ์ดังต่อไปนี้
150
100
60
30
10
ifhdl = open('test_file_3.txt', 'r')
# วนลูปแต่ละบรรทัดในไฟล์ ifhdl
for line in ifhdl.readlines():
# แตกบรรทัดออกเป็น token ด้วยคำสั่ง split
tokens = line.strip().split()
# ตัวแปรเก็บผลรวมรายบรรทัด
my_sum = 0
for token in tokens:
# แปลงแต่ละคำให้กลายเป็นตัวเลขจำนวนเต็ม
num = int(token)
# คำนวณผลรวมของบรรทัดนั้น
my_sum = my_sum + num
print(my_sum)
ifhdl.close()
150
100
60
30
10
ในบางครั้งเราจำเป็นต้องทำกระบวนการบางอย่างซ้ำๆ กัน แต่ว่าเปลี่ยนค่าตัวแปรที่ควบคุมกระบวนการ (ซึ่งเรียกว่า พารามิเตอร์ – parameter) เหล่านั้นไปตามสถานการณ์ ทำให้เราต้องก็อปปี้แปะโค้ดและแก้โค้ดซ้ำไปซ้ำมา
def
(ย่อมาจากคำว่า define) ดังนี้ครับ
def <ชื่อฟังก์ชัน> ( <รายการพารามิเตอร์> ) :
<กระบวนการ>
def print_student(name, age, height):
print(f'Name : {name}')
print(f'Age : {age:d} y/o')
print(f'Height : {height:6.2f} cm')
print()
student_scores = [
('John', 13, 165.5), ('Mary', 14, 173.0), ('Cindy', 12, 163.5)
]
for name, age, height in student_scores:
print_student(name, age, height)
Name : John
Age : 13 y/o
Height : 165.50 cm
Name : Mary
Age : 14 y/o
Height : 173.00 cm
Name : Cindy
Age : 12 y/o
Height : 163.50 cm
ในแบบฝึกหัดนี้ เราจะมาหัดแยกแยะพารามิเตอร์ออกจากกระบวนการ เพื่อมานิยามฟังก์ชันกันครับ
house_transactions = [
('Salary', +60000.0),
('Food', -10000.0),
('House mortgage', -20000.0),
('Consultancy', +20000.0),
('Credit card', -10000.0)
]
patisserie_transactions = [
('Flour', -2000.0),
('Cake sales', +30000.0),
('Tea sales', +10000.0),
('Staff salary', -15000.0),
('Electricity', -3000.0)
]
print(57 * '-')
for house_item, house_income in house_transactions:
if house_income > 0:
print(f'| {house_item:25} | {house_income:>25.2f} |')
else:
print(f'| {house_item:25} | {house_income:<25.2f} |')
print(57 * '-')
print()
print(57 * '-')
for shop_item, shop_income in patisserie_transactions:
if shop_income > 0:
print(f'| {shop_item:25} | {shop_income:>25.2f} |')
else:
print(f'| {shop_item:25} | {shop_income:<25.2f} |')
print(57 * '-')
print()
---------------------------------------------------------
| Salary | 60000.00 |
| Food | -10000.00 |
| House mortgage | -20000.00 |
| Consultancy | 20000.00 |
| Credit card | -10000.00 |
---------------------------------------------------------
---------------------------------------------------------
| Flour | -2000.00 |
| Cake sales | 30000.00 |
| Tea sales | 10000.00 |
| Staff salary | -15000.00 |
| Electricity | -3000.00 |
---------------------------------------------------------
print_transactions
def print_transactions(transactions):
print(57 * '-')
for item, income in transactions:
if income > 0:
print(f'| {item:25} | {income:>25.2f} |')
else:
print(f'| {item:25} | {income:<25.2f} |')
print(57 * '-')
print()
print_transactions
แทนhouse_transactions = [
('Salary', +60000.0),
('Food', -10000.0),
('House mortgage', -20000.0),
('Consultancy', +20000.0),
('Credit card', -10000.0)
]
patisserie_transactions = [
('Flour', -2000.0),
('Cake sales', +30000.0),
('Tea sales', +10000.0),
('Staff salary', -15000.0),
('Electricity', -3000.0)
]
print_transactions(house_transactions) # เติมโค้ดที่นี่
print_transactions(patisserie_transactions) # เติมโค้ดที่นี่
---------------------------------------------------------
| Salary | 60000.00 |
| Food | -10000.00 |
| House mortgage | -20000.00 |
| Consultancy | 20000.00 |
| Credit card | -10000.00 |
---------------------------------------------------------
---------------------------------------------------------
| Flour | -2000.00 |
| Cake sales | 30000.00 |
| Tea sales | 10000.00 |
| Staff salary | -15000.00 |
| Electricity | -3000.00 |
---------------------------------------------------------
return
นอกจากฟังก์ชันจะรวบรวมกระบวนการให้เป็นหน่วยเดียวได้แล้ว เรายังสามารถกำหนดให้ฟังก์ชันทำการคำนวณบางอย่างในกระบวนการ แล้วคืนค่าผลลัพธ์กลับออกมาได้อีกด้วย
return
โดยมีรูปแบบคือ
return <ค่าที่คืนกลับไป>
def average(items):
my_sum = 0.0
for item in items:
my_sum = my_sum + item
return my_sum / len(items)
student_heights = [163.5, 150.0, 167.0, 161.25, 170.0]
avg = average(student_heights)
print(f'The average of student heights is {avg:8.2f}.')
The average of student heights is 162.35.
ค่าความแปรปรวน (variance) เป็นมาตรวัดทางสถิติเพื่อบอกว่า ข้อมูลของเรากระจัดกระจายมากแค่ไหน โดยเทียบจากผลรวมของระยะห่างระหว่างข้อมูลแต่ละตัวกับค่าเฉลี่ย ระยะห่างตัวนี้คำนวณได้จากการนำข้อมูลกับค่าเฉลี่ยมาลบกันแล้วยกกำลัง 2 นั่นเองครับ
จงนิยามฟังก์ชันที่คำนวณค่าความแปรปรวนของข้อมูล $x_1, x_2, x_3, \ldots, x_N$ ซึ่งการคำนวณจะเป็นไปตามสูตรต่อไปนี้
\[\mathrm{Var}(x_1, x_2, x_3, \ldots, x_N) = \frac{1}{N - 1} \sum_{k = 1}^{N} \left( x_k - \bar{x} \right)^2\]เมื่อ $\bar{x}$ คือค่าเฉลี่ยของข้อมูล ซึ่งสามารถคำนวณได้จากฟังก์ชัน average
ซึ่งได้เตรียมไว้ให้แล้วครับ
**คำเตือน:** เมื่อคำนวณค่าความแปรปรวนได้แล้ว อย่าลืมใช้คำสั่ง return
เพื่อคืนผลลัพธ์ออกไปด้วยนะครับ
# ฟังก์ชันสำหรับคำนวณค่าเฉลี่ย
def average(items):
my_sum = 0.0
for item in items:
my_sum = my_sum + item
return my_sum / len(items)
# ฟังก์ชันสำหรับคำนวณค่าความแปรปรวน
def variance(items):
return (1/len(items)) * sum([(item - average(items))**2 for item in items])
เมื่อเขียนโปรแกรมเสร็จแล้ว ท่านสามารถทดสอบโปรแกรมได้ตรงนี้ครับ
student_heights = [163.5, 150.0, 167.0, 161.25, 170.0]
avg = average(student_heights)
var = variance(student_heights)
print(f'The average of student heights is {avg:8.2f}.')
print(f'The variance of student heights is {var:8.2f}.')
The average of student heights is 162.35.
The variance of student heights is 47.04.
return
เราสามารถหยุดการทำงานของฟังก์ชันกลางคันได้ ด้วยคำสั่ง return
โดยโปรแกรมจะออกจากฟังก์ชันทันทีครับ
return
นี้เราอาจจะใส่ค่าที่คืนกลับไปก็ได้ หรือไม่ใส่ลงไปก็ได้
n
เป็น 0 หรือ 1 ฟังก์ชันนี้จะคืนค่า 1 ออกไปแล้วหยุดทำงานทันทีครับ# คำนวณค่า factorial ของจำนวนเต็ม n
def factorial(n):
# หากค่า n เป็น 0 หรือ 1
if n in [0, 1]:
# ให้คืนค่า 1 กลับไป แล้วหยุดการทำงานทันที
return 1
# วนลูปคูณเลข
result = 1.0
for i in range(2, n + 1):
result = result * i
# คืนผลลัพธ์กลับออกไป
return result
factorial
กันครับprint(factorial(0))
print(factorial(20))
1
2.43290200817664e+18
ในกรณีที่ฟังก์ชันเป็นเพียงการรวบรวมกระบวนการให้เป็นหน่วย ไม่ได้มีจุดประสงค์จะคืนค่ากลับออกไป เราก็ยังสามารถใช้คำสั่ง return
ได้ด้วย เพียงแต่เราไม่ต้องระบุค่าคืนกลับเท่านั้นเองครับ
ในฟังก์ชันด้านล่างนี้ ถ้าหากพารามิเตอร์ age
มีค่า 60 ขึ้นไป ฟังก์ชันจะพิมพ์ข้อความ --Senior--
แล้วจบการทำงานทันที
def print_student(name, age, height):
# หาก age มีค่า 60 ขึ้นไป
if age >= 60:
print('--Senior--')
print()
# หยุดการทำงานของฟังก์ชัน
return
print(f'Name : {name}')
print(f'Age : {age:d} y/o')
print(f'Height : {height:6.2f} cm')
print()
student_scores = [
('John', 13, 165.5), ('Mary', 14, 173.0), ('Cindy', 12, 163.5),
('Magdalene', 65, 165.5), ('Eugene', 15, 177.0), ('Rupert', 12, 153.5)
]
for name, age, height in student_scores:
print_student(name, age, height)
Name : John
Age : 13 y/o
Height : 165.50 cm
Name : Mary
Age : 14 y/o
Height : 173.00 cm
Name : Cindy
Age : 12 y/o
Height : 163.50 cm
--Senior--
Name : Eugene
Age : 15 y/o
Height : 177.00 cm
Name : Rupert
Age : 12 y/o
Height : 153.50 cm
โปรแกรมเมอร์ที่ดีจะมีความสามารถที่จะทำให้โปรแกรมเมอร์คนอื่นสามารถอ่านโค้ดของเขารู้เรื่องได้ในภายหลัง
สมมติว่าเราได้รับหน้าที่ให้วิเคราะห์และทำให้โค้ดดังต่อไปนี้อ่านง่ายขึ้น เมื่อเราอ่านโค้ด เราก็จะพบว่าโปรแกรมเมอร์ที่เขียนโค้ดนี้ขึ้นมา ตั้งชื่อตัวแปร พารามิเตอร์ และฟังก์ชันไม่สื่อความหมายเลย นั่นคือแต่ละชื่อไม่ได้สะท้อนหน้าที่การทำงานของมันเลย
จงวิเคราะห์โค้ด และแก้ไขชื่อตัวแปร พารามิเตอร์ และฟังก์ชันให้สื่อความหมายตามที่คอมเมนต์ไว้ครับ
# คำนวณค่าเฉลี่ยของข้อมูล
def average(items):
# ผลรวมของข้อมูล
summation = 0.0
# ไล่ลูปข้อมูลแต่ละตัว
for num in items:
summation = summation + num
return summation / len(items)
# คำนวณค่าความแปรปรวนของข้อมูล
def variance(xs):
# ถ้าข้อมูลมีแค่ตัวเดียวหรือไม่มีเลย ให้ตอบ 0
if len(xs) <= 1:
return 0.0
# ค่าเฉลี่ยของข้อมูล
a = average(xs)
# ผลรวมของระยะทาง
s = 0.0
# ไล่ลูปข้อมูลแต่ละตัว
for x in xs:
s = s + (x - a)**2
return s / (len(xs) - 1)
เมื่อท่านได้แก้ไขชื่อต่างๆ เรียบร้อยแล้ว ท่านสามารถทดสอบโปรแกรมของท่านได้ตรงนี้ครับ
student_heights = [163.5, 150.0, 167.0, 161.25, 170.0]
# ค่าเฉลี่ยของความสูง
avg = average(student_heights)
# ค่าความแปรปรวนของความสูง
var = variance(student_heights)
print(f'Student heights = {student_heights}')
print(f'The average is {avg:9.2f}.')
print(f'The variance is {var:8.2f}.')
Student heights = [163.5, 150.0, 167.0, 161.25, 170.0]
The average is 162.35.
The variance is 58.80.
หากเราพบว่าฟังก์ชันใดมีจำนวนพารามิเตอร์เยอะๆ (เช่น เกิน 5 ตัว) ให้เราลองสังเกตความสัมพันธ์ของพารามิเตอร์และการทำงานของโค้ดดูก่อนครับ
หากเราสามารถจัดกลุ่มพารามิเตอร์และโค้ดที่เกี่ยวข้องได้ ให้เราพิจารณาที่จะแยกทั้งกลุ่มนี้ไปตั้งเป็นฟังก์ชันใหม่แล้วเรียกใช้ฟังก์ชันนี้แทน โค้ดที่ได้น่าจะอ่านง่ายขึ้นเยอะครับ
ถ้าเราสังเกตฟังก์ชัน print_students
ด้านล่างนี้ จะพบว่าฟังก์ชันนี้มีพารามิเตอร์ 9 ตัว ในแบบฝึกหัดนี้ เราจะมาหัดปรับโค้ดที่มีพารามิเตอร์เยอะๆ ให้อ่านง่ายขึ้นด้วยการรีแฟคเตอร์โค้ดกันครับ
พารามิเตอร์ในโค้ดที่ด้านล่างนี้สามารถแบ่งกลุ่มได้เป็นกี่กลุ่มครับ?
def print_students(name1, name2, name3, age1, age2, age3, height1, height2, height3):
print(f'Name : {name1}')
print(f'Age : {age1:d} y/o')
print(f'Height : {height1:6.2f} cm')
print()
print(f'Name : {name2}')
print(f'Age : {age2:d} y/o')
print(f'Height : {height2:6.2f} cm')
print()
print(f'Name : {name3}')
print(f'Age : {age3:d} y/o')
print(f'Height : {height3:6.2f} cm')
print()
ท่านลองยุบฟังก์ชัน print_students
ที่ด้านบนให้กลายเป็นฟังก์ชัน print_student
ที่รับข้อมูลของนักเรียนเพียงคนเดียวดูครับ
def print_student(name, age, height):
print(f'Name : {name}')
print(f'Age : {age:d} y/o')
print(f'Height : {height:6.2f} cm')
print()
ในกิจกรรมที่แล้ว เราได้เรียนรู้การรวบรวมกระบวนการให้เป็นหน่วยด้วยฟังก์ชัน นั่นคือเราพยายามออกแบบโปรแกรมโดยเน้นที่กระบวนการของการกระทำ
แต่ในบางกรณี การออกแบบโปรแกรมโดยเน้นกระบวนการอาจจะทำให้การเขียนโปรแกรมยุ่งยากมากขึ้น
pi = 3.1415926
# คำนวณพื้นที่วงกลม
def area_circle(circle):
return pi * circle['radius']**2
# คำนวณเส้นรอบวงของวงกลม
def circumference_circle(circle):
return 2 * pi * circle['radius']
# หาค่าสีของวงกลม
def color_circle(circle):
return circle['color']
# คำนวณพื้นที่จัตุรัส
def area_square(square):
return square['side']**2
# คำนวณเส้นรอบวงจัตุรัส
def circumference_square(square):
return 4 * square['side']
# หาค่าสีของจัตุรัส
def color_square(square):
return square['color']
จะสังเกตได้ว่า เรายังต้องเขียนฟังก์ชันซ้ำกันอยู่หลายอัน แม้ว่าฟังก์ชันเหล่านี้จะทำงานคล้ายคลึงกันก็ตาม เช่น color_circle
กับ color_square
นอกจากนี้ เวลาที่เราจะสร้างวัตถุใหม่ขึ้นมา เราจะสร้างด้วยดิกชันนารี และเราก็จะต้องก็อปปี้โครงสร้างของดิกชันนารีให้เหมือนเปี๊ยบด้วย มิเช่นนั้นโปรแกรมก็อาจจะทำงานผิดพลาดได้ เพราะอ้างผิดคีย์หรืออ้างคีย์ไม่ครบ เช่น
circle1 = {'radius': 30.0, 'color': 'red'}
circle2 = {'radius': 15.5, 'color': 'green'}
circle3 = {'radius': 10.0, 'color': 'blue'}
square1 = {'side': 10.0, 'color': 'yellow'}
square2 = {'side': 15.0, 'color': 'orange'}
square3 = {'side': 5.75, 'color': 'pink'}
print(f'Area of circle1 = {area_circle(circle1)}')
print(f'Circumference of circle2 = {circumference_circle(circle2)}')
print(f'Color of circle3 = {color_circle(circle3)}')
print()
print(f'Area of square1 = {area_square(square1)}')
print(f'Circumference of square2 = {circumference_square(square2)}')
print(f'Color of square3 = {color_square(square3)}')
Area of circle1 = 2827.43334
Circumference of circle2 = 97.3893706
Color of circle3 = blue
Area of square1 = 100.0
Circumference of square2 = 60.0
Color of square3 = pink
เพื่อให้อ่านโค้ดได้ง่ายขึ้น เรายังสามารถรวบรวมกระบวนการตามชนิดของวัตถุได้อีกด้วย โดยวัตถุแต่ละชนิดจะมีฟังก์ชันหน้าตาเหมือนกัน แต่ไส้ในของแต่ละฟังก์ชันจะแตกต่างกันไปตามชนิดของวัตถุ
การรวบรวมกระบวนการตามชนิดของวัตถุนี้ เราเรียกว่า การโปรแกรมเชิงวัตถุ (object-oriented programming หรือ OOP)
class
ดังรูปแบบต่อไปนี้
class <ชื่อคลาส> :
<รายการฟังก์ชัน>
เราสามารถนิยามฟังก์ชันภายในคลาสได้ด้วยคำสั่ง def
เหมือนกับฟังก์ชันปกติเลยครับ ฟังก์ชันภายในคลาสนี้มีชื่อเรียกอย่างเป็นทางการว่า เมธอด (method)
เมธอดสำคัญของคลาสคือ คอนสตรักเตอร์ (constructor) มีไว้สำหรับสร้างวัตถุ (object) จากคลาส โดยคอนสตรักเตอร์จะใช้ชื่อเมธอดว่า __init__
(โปรดสังเกตว่าชื่อ init
จะมีขีดเส้นใต้ 2 อันที่ด้านหน้าและด้านหลัง)
self
สำหรับอ้างถึงวัตถุที่เรากำลังจะสร้างCircle
และคอนสตรักเตอร์ของคลาสนี้ได้ดังนี้class Circle:
def __init__(self, color, radius):
self.color = color
self.radius = radius
คอนสตรักเตอร์ของคลาส Circle
จะรับพารามิเตอร์สำหรับคลาส 2 ตัวคือ color
และ radius
self
เช่น
def __init__(self, color, radius):
self.color = color
self.radius = radius
Circle
ได้อีกด้วย ในตัวอย่างข้างล่างนี่ เราจะนิยามฟังก์ชันเพิ่มอีก 3 ตัว ได้แก่ area
, circumference
, และ get_color
pi = 3.1415926
class Circle:
# คอนสตรักเตอร์
def __init__(self, color, radius):
# กำหนดสีจากพารามิเตอร์
self.color = color
# กำหนดรัศมีจากพารามิเตอร์
self.radius = radius
# คำนวณพื้นที่
def area(self):
return pi * self.radius**2
# คำนวณเส้นรอบวง
def circumference(self):
return 2 * pi * self.radius
# หาค่าสี
def get_color(self):
return self.color
เราสามารถประกาศวัตถุของคลาสได้โดยเรียกชื่อคลาส ตามด้วยพารามิเตอร์ในคอนสตรักเตอร์
ในตัวอย่างด้านล่างนี้ เราประกาศวัตถุของคลาส Circle
ออกมา 3 ตัว สังเกตว่าคราวนี้เราจะสร้างวัตถุได้ง่ายกว่าการสร้างดิกชันนารีเองมากครับ
จริงๆ แล้วการสร้างคลาสเปรียบเสมือนการสร้างแม่พิมพ์ (template) เพื่อปั๊มป์วัตถุจำนวนมากๆ ที่มีหน้าตาคล้ายคลึงกันออกมา
circle1 = Circle('red', 30.0)
circle2 = Circle('green', 15.5)
circle3 = Circle('blue', 10.0)
<วัตถุ>.<เมธอด>(<พารามิเตอร์>)
ครับprint('Area of circle1 =', circle1.area())
print('Circumference of circle2 =', circle2.circumference())
print('Color of circle3 =', circle3.get_color())
Area of circle1 = 2827.43334
Circumference of circle2 = 97.3893706
Color of circle3 = blue
คราวนี้เราจะมานิยามคลาส Square
กันบ้างนะครับ คลาส Square
จะมีคุณสมบัติ 2 ตัว คือ side
(ความยาวด้าน) และ color
(สี) และมีเมธอด 3 ตัว คือ area
(คำนวณพื้นที่), circumference
(คำนวณเส้นรอบวง), และ get_color
(หาค่าสี) ครับ
class Square:
# คอนสตรักเตอร์
def __init__(self, color, side):
# กำหนดค่าสี
self.color = color
# กำหนดความยาวด้าน
self.side = int(side)
# คำนวณพื้นที่
def area(self):
return self.side ** 2
# คำนวณเส้นรอบวง
def circumference(self):
return self.side * 4
# หาค่าสี
def get_color(self):
return self.color
จากนั้นเราจะมาลองสร้างวัตถุจากคลาส Square
กันดูบ้างครับ
square1 = Square('red', 10.0)
square2 = Square('green', 15.0)
square3 = Square('blue', 5.75)
และมาลองเรียกเมธอดของ Square
กันดูครับ
print('Area of square1 =', square1.area())
print('Circumference of square2 =', square2.circumference())
print('Color of square3 =', square3.get_color())
Area of square1 = 100
Circumference of square2 = 60
Color of square3 = blue
ข้อดีอีกข้อหนึ่งของการสร้างคลาสก็คือ เราสามารถถ่ายทอดคุณสมบัติของคลาสให้กับคลาสลูกหลานได้อีกด้วย
เช่น ถ้าเราสังเกตคลาส Circle
และ Square
ให้ดี เราจะพบว่าทั้งสองคลาสนี้มีคุณสมบัติร่วมกันคือ มี color
(สี) เหมือนกัน และมีเมธอดร่วมกันคือ get_color
(หาค่าสี)
ที่เป็นเช่นนี้ก็เพราะว่า จริงๆ แล้วคลาส Circle
(วงกลม) และ Square
(สี่เหลี่ยมจัตุรัส) ต่างก็เป็นรูปทรงด้วยกันทั้งสิ้น เราจึงมองได้ว่าทั้งสองคลาสนี้เป็นคลาสลูกของคลาส Shape
ด้วยกันทั้งสิ้น
class Shape:
def __init__(self, color):
self.color = color
# หาค่าสี
def get_color(self):
return self.color
class
ได้ตามรูปแบบนี้ครับ
class <คลาสลูก> ( <คลาสแม่> ) :
<รายการเมธอด>
เมื่อเราประกาศคลาสลูกขึ้นมาแล้ว เราจะต้องนิยามคอนสตรักเตอร์ให้เรียกใช้คอนสตรักเตอร์ของคลาสแม่ด้วยครับ
วิธีการเรียกใช้คอนสตรักเตอร์ของคลาสแม่คือใช้คำสั่ง super(<คลาสลูก>, self).__init__(<พารามิเตอร์สำหรับคลาสแม่>)
Circle
ให้เป็นคลาสลูกของ Shape
ได้ดังนี้class Circle(Shape):
def __init__(self, color, radius):
# นี่คือวิธีการเรียกคอนสตรักเตอร์ของคลาสแม่ โดยเราจะต้องป้อนพารามิเตอร์ที่จำเป็นสำหรับคลาสแม่เข้าไปด้วย
super(Circle, self).__init__(color)
# หลังจากนั้นให้เรากำหนดคุณสมบัติของคลาสลูกตามปกติ
self.radius = radius
# คำนวณพื้นที่
def area(self):
return pi * self.radius**2
# คำนวณเส้นรอบวง
def circumference(self):
return 2 * pi * self.radius
get_color
อีกแล้ว เพราะฟังก์ชันนี้ได้รับการถ่ายทอดมาจากคลาส Shape
อยู่แล้วนั่นเองครับmy_circle = Circle('red', 30.0)
print('Area =', my_circle.area())
print('Circumference =', my_circle.circumference())
print('Color =', my_circle.get_color())
Area = 2827.43334
Circumference = 188.495556
Color = red
จงออกแบบคลาส Square
ให้เป็นคลาสลูกของ Shape
โดยเลียนแบบจากแบบฝึกหัด 16.1
class Square(Shape):
def __init__(self, color, side):
# เรียกใช้คอนสตรักเตอร์ของคลาสแม่ อย่าลืมป้อนพารามิเตอร์ที่จำเป็นเข้าไปด้วย
super().__init__(color)
# กำหนดคุณสมบัติของคลาสลูกตามปกติ
self.side = int(side)
# คำนวณพื้นที่
def area(self):
return self.side ** 2
# คำนวณเส้นรอบวง
def circumference(self):
return self.side * 4
อย่าลืมทดสอบนะครับว่า โค้ดนี้ใช้งานได้จริงหรือเปล่า
my_square = Square('red', 10.0)
print('Area =', my_square.area())
print('Circumference =', my_square.circumference())
print('Color =', my_square.get_color())
Area = 100
Circumference = 40
Color = red
สมมติว่าเราต้องการออกแบบคลาสสำหรับรีโมทคอนโทรล หน้าที่หลักของรีโมทคอนโทรลคือ เปิด/ปิด อุปกรณ์ไฟฟ้า แต่รีโมทคอนโทรลสำหรับอุปกรณ์ไฟฟ้าแต่ละชนิดก็จะมีหน้าที่เฉพาะแตกต่างกันออกไป เช่น
รีโมทโทรทัศน์ก็จะมีฟังก์ชันสำหรับเปลี่ยนช่อง เพิ่ม/ลดเสียง และปรับสีและความสว่าง
ในขณะที่รีโมทแอร์ก็จะมีฟังก์ชันในการลด/เพิ่มอุณหภูมิ และปรับการสวิงใบพัด เป็นต้น
ในโจทย์ข้อนี้ เราจะให้ท่านออกแบบคลาสทั้งหมด 3 คลาสด้วยกัน โดยมีคลาสแม่คือคลาสรีโมทคอนโทรล RemoteControl
และมีคลาสลูกอีก 2 คลาสคือ คลาสรีโมทโทรทัศน์ TVRemoteControl
และคลาสรีโมทแอร์ ACRemoteControl
RemoteControl
คลาสแม่สามารถเปิดและปิดสวิตช์ได้ โดยจะสลับค่าของคุณสมบัติ power
class RemoteControl:
def __init__(self):
# ปิดสวิตช์ของอุปกรณ์ไฟฟ้าไว้ก่อน
self.power = False
# สลับสวิตช์เปิด/ปิด
def toggle_power(self):
print(f'Toggle power: {self.power} -> ', end='')
# สลับค่าของคุณสมบัติ power (คำใบ้: คำสั่ง not)
self.power = not self.power
print(f'{self.power}')
ทดสอบกันนิดนึงว่า คลาสนี้ใช้ได้หรือเปล่า
rctrl = RemoteControl()
# ค่าสวิตช์ควรจะสลับไปสลับมา
rctrl.toggle_power()
rctrl.toggle_power()
rctrl.toggle_power()
Toggle power: False -> True
Toggle power: True -> False
Toggle power: False -> True
TVRemoteControl
: รีโมทโทรทัศน์คลาส TVRemoteControl
จะเปลี่ยนช่องได้ เพิ่มเสียงได้ และลดเสียงได้ โดย
ช่องจะต้องเป็นจำนวนเต็มตั้งแต่ 1 จนถึง 9
ระดับเสียงจะมีค่าตั้งแต่ 0 จนถึง 10 หากลดเสียงหรือเพิ่มเสียงจนเกินจากค่านี้ ค่าก็จะไม่เปลี่ยนแปลงอีก
class TVRemoteControl(RemoteControl):
def __init__(self):
# เรียกคอนสตรักเตอร์ของคลาสแม่
super().__init__()
# กำหนดคุณสมบัติเฉพาะของคลาสลูก
self.channel = 0
self.volume = 5
# เปลี่ยนช่องให้เป็นช่องใหม่ที่กำหนด
def change_channel(self, new_channel):
print(f'Change channel: {self.channel} -> ', end='')
# เปลี่ยนช่อง โดยช่องจะต้องเป็นจำนวนเต็มอยู่ในช่วง 0 ถึง 9 ไม่เช่นนั้นก็จะไม่เปลี่ยนช่อง
if 0 <= new_channel <= 9:
self.channel = new_channel
print(f'{self.channel}')
# เพิ่มเสียง
def increase_volume(self):
print(f'Increase volume: {self.volume} -> ', end='')
# เพิ่มเสียง โดยค่าระดับเสียงต้องไม่เกิน 10
if self.volume < 10:
self.volume += 1
print(f'{self.volume}')
# ลดเสียง
def decrease_volume(self):
print(f'Decrease volume: {self.volume} -> ', end='')
# ลดเสียง โดยค่าระดับเสียงต้องไม่ต่ำกว่า 0
if self.volume > 0:
self.volume -= 1
print(f'{self.volume}')
ทดสอบโค้ดกันหน่อยครับ
tvremote = TVRemoteControl()
# ลองเปลี่ยนช่องตามปกติ
tvremote.change_channel(1)
tvremote.change_channel(2)
print()
# ลองเปลี่ยนช่องที่เป็นไปไม่ได้ ช่องไม่ควรจะเปลี่ยน
tvremote.change_channel(-1)
tvremote.change_channel(11)
print()
# ลองเพิ่มเสียงจนหลุดช่วง ระดับเสียงไม่ควรจะเพิ่มอีก
for i in range(11):
tvremote.increase_volume()
print()
# ลองลดเสียงไปจนหลุดช่วง ระดับเสียงไม่ควรจะลดอีก
for i in range(11):
tvremote.decrease_volume()
Change channel: 0 -> 1
Change channel: 1 -> 2
Change channel: 2 -> 2
Change channel: 2 -> 2
Increase volume: 5 -> 6
Increase volume: 6 -> 7
Increase volume: 7 -> 8
Increase volume: 8 -> 9
Increase volume: 9 -> 10
Increase volume: 10 -> 10
Increase volume: 10 -> 10
Increase volume: 10 -> 10
Increase volume: 10 -> 10
Increase volume: 10 -> 10
Increase volume: 10 -> 10
Decrease volume: 10 -> 9
Decrease volume: 9 -> 8
Decrease volume: 8 -> 7
Decrease volume: 7 -> 6
Decrease volume: 6 -> 5
Decrease volume: 5 -> 4
Decrease volume: 4 -> 3
Decrease volume: 3 -> 2
Decrease volume: 2 -> 1
Decrease volume: 1 -> 0
Decrease volume: 0 -> 0
ACRemoteControl
: รีโมทแอร์คลาส ACRemoteControl
จะเพิ่มระดับอุณหภูมิได้ ลดระดับอุณหภูมิได้ และเปิด/ปิดการสวิงใบพัดได้ ทั้งนี้อุณหภูมิจะต้องอยู่ในช่วง 15-35 องศาเซลเซียสเท่านั้น
class ACRemoteControl(RemoteControl):
def __init__(self):
# เรียกคอนสตรักเตอร์ของคลาสแม่
super().__init__()
# กำหนดคุณสมบัติเฉพาะของคลาสลูก
self.temperature = 25
self.fan_swing = True
# เพิ่มอุณหภูมิ
def increase_temperature(self):
print(f'Increase temperature: {self.temperature} -> ', end='')
# เพิ่มอุณหภูมิ โดยค่าระดับอุณหภูมิต้องไม่เกิน 35
if self.temperature < 35:
self.temperature += 1
print(f'{self.temperature}')
# ลดอุณหภูมิ
def decrease_temperature(self):
print(f'Decrease temperature: {self.temperature} -> ', end='')
# ลดอุณหภูมิ โดยค่าระดับเสียงต้องไม่ต่ำกว่า 15
if self.temperature > 15:
self.temperature -= 1
print(f'{self.temperature}')
# สลับการเปิด/ปิดสวิงใบพัด
def toggle_fan_swing(self):
print(f'Toggle fan swing: {self.fan_swing} -> ', end='')
# สลับการเปิด/ปิดสวิงใบพัด (คำใบ้: คำสั่ง not)
self.fan_swing = not self.fan_swing
print(f'{self.fan_swing}')
ลองทดสอบโค้ดด้านบนดูนะครับ ว่าทำงานได้หรือเปล่า
acremote = ACRemoteControl()
# ลองสลับสวิตช์การสวิงพัดลม
acremote.toggle_fan_swing()
acremote.toggle_fan_swing()
acremote.toggle_fan_swing()
print()
# ลองเพิ่มอุณหภูมิจนหลุดช่วง ระดับอุณหภูมิไม่ควรจะเพิ่มอีก
for i in range(12):
acremote.increase_temperature()
print()
# ลองลดอุณหภูมิไปจนหลุดช่วง ระดับอุณหภูมิไม่ควรจะลดอีก
acremote.temperature = 20
for i in range(12):
acremote.decrease_temperature()
Toggle fan swing: True -> False
Toggle fan swing: False -> True
Toggle fan swing: True -> False
Increase temperature: 25 -> 26
Increase temperature: 26 -> 27
Increase temperature: 27 -> 28
Increase temperature: 28 -> 29
Increase temperature: 29 -> 30
Increase temperature: 30 -> 31
Increase temperature: 31 -> 32
Increase temperature: 32 -> 33
Increase temperature: 33 -> 34
Increase temperature: 34 -> 35
Increase temperature: 35 -> 35
Increase temperature: 35 -> 35
Decrease temperature: 20 -> 19
Decrease temperature: 19 -> 18
Decrease temperature: 18 -> 17
Decrease temperature: 17 -> 16
Decrease temperature: 16 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
Decrease temperature: 15 -> 15
ฟังก์ชันเวียนเกิด (recursive function) คือฟังก์ชันที่มีการเรียกตัวเองซ้ำไปซ้ำมา
เช่น ฟังก์ชันคำนวณค่าแฟคทอเรียล (factorial) $ n! = 1 \times 2 \times 3 \times \ldots \times n $ สามารถเขียนให้อยู่ในรูปฟังก์ชันเวียนเกิดได้ดังนี้
# ฟังก์ชันแฟคทอเรียล
def factorial(n):
# เงื่อนไขการหยุดทำงาน
if n == 0:
return 1
# ส่วนเวียนเกิด
else:
return n * factorial(n - 1) # สังเกตว่าจะมีการเรียกฟังก์ชัน factorial ซ้ำที่ตรงนี้
factorial(10)
3628800
ในบางครั้งการคำนวณฟังก์ชันเวียนเกิดจะมีสิ่งที่ต้องคำนวณซ้ำกันด้วย
เช่น อนุกรมของฟิโบนัชชีจะเป็นดังนี้ครับ \(0, 1, 1, 2, 3, 5, 8, 13, 21, \ldots\) โดยตัวเลขถัดไปจะเกิดจากการเอาตัวเลข 2 ตัวก่อนหน้ามาบวกกัน
ฟังก์ชัน Fibonacci (ฟิโบนัชชี) จะมีนิยามดังนี้ครับ
def fibonacci(n):
if n == 0 or n == 1:
return n
else:
return fibonacci(n - 1) + fibonacci(n - 2)
fibonacci(4)
3
อย่างไรก็ตาม ในการคำนวณค่า $\mathrm{fibonacci}(4)$ เราต้องคำนวณค่าของ $ \mathrm{fibonacci}(2) $ ซ้ำสองรอบ
เราไม่จำเป็นต้องคำนวณสิ่งที่เคยคำนวณไปแล้วก็ได้ครับ เราควรจะบันทึกสิ่งที่เราเคยคำนวณไว้แล้วเก็บไว้ในหน่วยความจำ เราเรียกกระบวนการนี้ว่า การจดจำรายทาง (memoization)
ในตัวอย่างด้านล่างนี้เราใช้การจดจำรายทางคำตอบของฟังก์ชันฟิโบนัชชีด้วยการเก็บลงดิกชันนารีครับ
fibonacci_memory = {}
def fibonacci_memo(n):
if n not in fibonacci_memory:
if n == 0 or n == 1:
fibonacci_memory[n] = n
else:
fibonacci_memory[n] = fibonacci_memo(n - 1) + fibonacci_memo(n - 2)
return fibonacci_memory[n]
fibonacci_memo(4)
3
fibonacci_memo(1000)
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
fibonacci_memory.clear()
for i in range(len(fibonacci_memory)):
print(fibonacci_memory[i])
fibonacci_memo(5)
for i in range(len(fibonacci_memory)):
print(fibonacci_memory[i])
0
1
1
2
3
5
**คำใบ้:** ขอแนะนำให้ใช้การจดจำรายทาง (memoization) เพื่อความรวดเร็วในการคำนวณ
memory_fibonacci = {} # สำหรับท่านที่เลือกใช้วิธีการจดจำรายทาง (memoization)
def fibonacci(n):
if n not in memory_fibonacci:
if n == 0 or n == 1:
memory_fibonacci[n] = n
else:
memory_fibonacci[n] = fibonacci(n - 1) + fibonacci(n - 2)
# print(memory_fibonacci)
return memory_fibonacci[n]
fibonacci(9)
34
**คำใบ้:** ขอแนะนำให้ใช้การจดจำรายทาง (memoization) เพื่อความรวดเร็วในการคำนวณ
memory_ackermann = {} # สำหรับท่านที่เลือกใช้วิธีการจดจำรายทาง (memoization)
def ackermann(m, n):
if (m, n) not in memory_ackermann:
if m == 0:
memory_ackermann[(m, n)] = n + 1
elif m > 0 and n == 0:
memory_ackermann[(m, n)] = ackermann(m - 1, 1)
elif m > 0 and n > 0:
memory_ackermann[(m, n)] = ackermann(m - 1, ackermann(m, n - 1))
# print(memory_ackermann)
return memory_ackermann[(m, n)]
ackermann(3, 5)
253
gettysburg_address
gettysburg_address = 'Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate -- we can not consecrate -- we can not hallow -- this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us -- that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion -- that we here highly resolve that these dead shall not have died in vain -- that this nation, under God, shall have a new birth of freedom -- and that government of the people, by the people, for the people, shall not perish from the earth.'
charfreq = {}
# นับความถี่ของแต่ละตัวอักษร เก็บค่าความถี่ลงในดิกชันนารี charfreq
for char in gettysburg_address:
if char not in charfreq:
charfreq[char] = 1
else:
charfreq[char] += 1
# พิมพ์ดิกชันนารีนั้นออกหน้าจอ
print(charfreq)
{'F': 1, 'o': 93, 'u': 21, 'r': 79, ' ': 277, 's': 44, 'c': 31, 'e': 165, 'a': 102, 'n': 76, 'd': 58, 'v': 24, 'y': 10, 'g': 27, 'f': 26, 't': 124, 'h': 80, 'b': 13, 'i': 65, ',': 22, 'w': 26, 'L': 1, 'p': 15, 'l': 41, 'm': 13, 'q': 1, '.': 10, 'N': 1, 'W': 2, '-': 15, 'I': 3, 'B': 1, 'T': 2, 'k': 3, 'G': 1}
23122018
สำหรับวันที่ 23 ธันวาคม 2018) แล้วคำนวณว่าในระหว่างนั้นมีวันเสาร์กี่วัน
%
(modulo) เช่น 4 % 3 = 1
ในขณะที่ 4 % 2 = 0
เป็นต้นimport datetime
import math
from_date="20122018"
to_date="23122020"
def calc_number_of_saturdays(fromdate, todate):
index_date="23122018"
date0=datetime.datetime.strptime(index_date, "%d%m%Y")
date1=datetime.datetime.strptime(from_date, "%d%m%Y")
date2=datetime.datetime.strptime(to_date, "%d%m%Y")
return (abs((date0-date1).days)+abs((date0-date2).days))//7
print(calc_number_of_saturdays(from_date, to_date))
104
chaosmap1 = [
'*******',
'* *',
'* *** *',
'* *** *',
'* *** *',
'*S***G*'
]
my answer =
(5, 1) (4, 1) (3, 1) (2, 1) (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (2, 5) (3, 5) (4, 5) (5, 5)
โดยตัวอักษรแต่ละตัวจะมีความหมายดังนี้
*
แทนเส้นทางที่เดินไปไม่ได้S
แทนจุดเริ่มต้น (start)G
แทนจุดเส้นชัย (goal)ให้เขียนโปรแกรมเพื่อหา**เส้นทางที่สั้นที่สุด** จากจุดเริ่มต้นไปยังเส้นชัย เช่น เส้นทางสั้นที่สุดของ chaosmap1
จะเป็นดังนี้
Route:
(5, 1) <START>
(4, 1)
(3, 1)
(2, 1)
(1, 1)
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(2, 5)
(3, 5)
(4, 5)
(5, 5) <GOAL>
**คำใบ้:** ขอแนะนำให้ใช้วิธีการจดจำรายทาง (memoization) เพื่อความรวดเร็วในการคำนวณ
chaosmap1 = [
'*******',
'* *',
'* *** *',
'* *** *',
'* *** *',
'*S***G*'
]
chaosmap2 = [
'*************S*******',
'* * *',
'* * *** ******* * * *',
'* * * * * * *',
'* * ***** ******* * *',
'* * * * * * *',
'******* *** * *** ***',
'* * * * *',
'* * ******* * * *** *',
'* * * * * * *',
'* *** ********* * * *',
'* * * * *',
'* * *** ********* * *',
'* * * * * * *',
'*** * * * ***** * ***',
'* * * * * * * *',
'* ***** * * *** *** *',
'* * * * * *',
'* ******* * * *** * *',
'* * * * *',
'*****G***************'
]
memory_traverse = {} # สำหรับท่านที่เลือกใช้วิธีการจดจำรายทาง (memoization)
memory_path = {}
best_path = []
# A* search algorithm
def traverse(chaosmap, show_result=True):
memory_path.clear()
best_path.clear()
start_pos = None
goal_pos = None
for y in range(len(chaosmap)):
for x in range(len(chaosmap[y])):
if chaosmap[y][x] == 'S':
start_pos = (x, y)
memory_path[(x, y)] = 0
elif chaosmap[y][x] == 'G':
goal_pos = (x, y)
if start_pos is None or goal_pos is None:
return False
queues = []
queues.append(start_pos)
while len(queues) > 0:
cur_pos = queues.pop(0)
if cur_pos == goal_pos:
break
for direction in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
new_pos = (cur_pos[0] + direction[0], cur_pos[1] + direction[1])
if (new_pos in memory_traverse) and memory_traverse[new_pos] is False:
continue
else:
memory_traverse[new_pos] = False
if new_pos[0] < 0 or new_pos[0] >= len(chaosmap[0]) or new_pos[1] < 0 or new_pos[1] >= len(chaosmap):
continue
if chaosmap[new_pos[1]][new_pos[0]] == '*':
continue
if new_pos in memory_path:
continue
memory_traverse[new_pos] = True
memory_path[new_pos] = memory_path[cur_pos] + 1
queues.append(new_pos)
# select best path in memory_path
cur_pos = goal_pos
while cur_pos != start_pos:
best_path.append(cur_pos)
for direction in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
new_pos = (cur_pos[0] + direction[0], cur_pos[1] + direction[1])
if new_pos in memory_path and memory_path[new_pos] == memory_path[cur_pos] - 1:
cur_pos = new_pos
break
best_path.append(start_pos)
best_path.reverse()
show_result and print('Route:\n'+'\n'.join([f'{str((x, y))}{" <START>" if best_path.index((x,y)) == 0 else ""}{" <GOAL>" if best_path.index((x,y)) == len(best_path) - 1 else ""}' for x, y in best_path]))
class Checker:
"""
Checking if the path is valid
"""
def __init__(self, **kwargs) -> None:
"""Initialize the checker"""
self.name = kwargs.get('name', 'Untitled')
self.chaosmap = kwargs.get('chaosmap', [])
self.memory_path = kwargs.get('memory_path', {})
self.best_path = kwargs.get('best_path', [])
self.wall = '*'
self.start = 'S'
self.goal = 'G'
self.walkpath = ' '
self.draw_wall = '████'
self.draw_walkpath = ' '
self.draw_walkpath_walked = '░░░░'
self.draw_start = 'SSSS'
self.draw_goal = 'GGGG'
self.width = len(self.draw_wall)
def __str__(self) -> str:
"""Return visualized chaosmap without any path.
Returns:
str: visualized chaosmap without any path.
"""
return self.__draw()
def __draw(self, **kwargs) -> str:
"""Return visualized chaosmap with path.
Args:
**kwargs:
path (list): Best path list.
start (tuple): start character marker.
goal (tuple): goal character marker.
wall (str): wall character maker.
walkpath (str): walkpath character marker.
draw_wall (str): wall character to be show when needed.
draw_walkpath (str): walkpath character to be show when needed.
draw_start (str): start character to be show when needed.
draw_goal (str): goal character to be show when needed.
blank (str): show instead of unknown charater.
Returns:
str: visualized chaosmap with path customized.
"""
wall = kwargs.get('wall', self.wall)
draw_wall = kwargs.get('draw_wall', self.draw_wall)
start = kwargs.get('start', self.start)
draw_start = kwargs.get('draw_start', self.draw_start)
goal = kwargs.get('goal', self.goal)
draw_goal = kwargs.get('draw_goal', self.draw_goal)
walkpath = kwargs.get('walkpath', self.walkpath)
draw_walkpath = kwargs.get('draw_walkpath', self.draw_walkpath)
draw_walkpath_walked = kwargs.get('draw_walkpath_walked', self.draw_walkpath_walked)
blank = kwargs.get('blank', ' ')
ret = f'Name: {self.name}\n' + ''.join([f'{str(num):^4}' for num in range(len(self.chaosmap[0]))] + ['\n'])
for y in range(len(self.chaosmap)):
for x in range(len(self.chaosmap[y])):
curr_char = self.chaosmap[y][x]
coord = {'x': x, 'y': y, 'step': self.memory_path[(x, y)] if (x,y) in self.memory_path else 0}
if (x, y) in self.best_path and self.chaosmap[y][x] not in [wall, start, goal]:
ret += draw_walkpath_walked.format_map(coord)
elif curr_char == wall:
ret += draw_wall.format_map(coord)
elif curr_char == start:
ret += draw_start.format_map(coord)
elif curr_char == goal:
ret += draw_goal.format_map(coord)
elif curr_char == walkpath:
ret += draw_walkpath.format_map(coord)
else:
ret += blank.format_map(coord)
ret += f'{y:^4}' + '\n'
return ret
def draw_trace(self,**kwargs) -> None:
print(self.__draw(draw_walkpath_walked='{step:>4}', draw_walkpath=' '))
def draw(self):
print(self.__draw())
_maze = chaosmap2
checking = {
'name': 'Random Maze',
'chaosmap': _maze,
'memory_path': memory_path,
'best_path': best_path,
}
traverse(_maze, show_result=False)
map = Checker(**checking)
map.draw_walkpath_walked = '░░░░'
map.draw_walkpath = ' '
map.draw_goal = ' GG '
map.draw_start = ' SS '
map.draw_wall = '////'
map.draw()
Name: Random Maze
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
//////////////////////////////////////////////////// SS //////////////////////////// 0
//// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░////░░░░░░░░░░░░ //// 1
//// ////░░░░//////////// ////////////////////////////░░░░////░░░░//// //// 2
//// ////░░░░//// ////░░░░░░░░░░░░░░░░░░░░░░░░░░░░////░░░░//// //// 3
//// ////░░░░////////////////////░░░░////////////////////////////░░░░//// //// 4
//// ////░░░░░░░░░░░░░░░░░░░░////░░░░░░░░░░░░//// ////░░░░//// //// 5
////////////////////////////░░░░////////////░░░░//// ////////////░░░░//////////// 6
////░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ////░░░░//// ////░░░░░░░░░░░░//// 7
////░░░░//// ////////////////////////////░░░░//// //// ////////////░░░░//// 8
////░░░░//// ////░░░░░░░░░░░░░░░░░░░░░░░░░░░░//// //// ////░░░░░░░░░░░░//// 9
////░░░░////////////░░░░//////////////////////////////////// ////░░░░//// //// 10
////░░░░░░░░░░░░////░░░░░░░░░░░░ ////░░░░//// //// 11
//// ////░░░░////////////░░░░////////////////////////////////////░░░░//// //// 12
//// ////░░░░ ////░░░░////░░░░░░░░░░░░░░░░░░░░░░░░░░░░////░░░░//// //// 13
////////////░░░░//// ////░░░░////░░░░////////////////////░░░░////░░░░//////////// 14
////░░░░░░░░░░░░//// ////░░░░////░░░░//// ////░░░░////░░░░░░░░░░░░//// 15
////░░░░////////////////////░░░░////░░░░//// ////////////░░░░////////////░░░░//// 16
////░░░░░░░░░░░░░░░░░░░░░░░░░░░░////░░░░//// ////░░░░░░░░░░░░////░░░░░░░░░░░░//// 17
//// ////////////////////////////░░░░//// ////░░░░////////////░░░░//// //// 18
//// ////░░░░░░░░░░░░░░░░░░░░//// ░░░░░░░░░░░░░░░░░░░░//// //// 19
//////////////////// GG //////////////////////////////////////////////////////////// 20