นี่คือรายวิชาแรกในสาขาวิทยาการคอมพิวเตอร์ของมหาวิทยาลัย: พื้นฐานการเขียนโปรแกรม
, สอนด้วย Python 3. โดยไม่จำเป็นต้องมีความรู้ด้านการเขียนโปรแกรมมาก่อน ทุกโปรแกรมใน
this handout is complete and runnable — type it, run it, change one line, and predict
ว่าจะเกิดอะไรขึ้นก่อนรันอีกครั้ง ลูป predict-then-run นี้คือทักษะทั้งหมด
การอ่านนิพจน์คือ "เปิดกล่อง คำนวณ ปิดกล่องใหม่": count * 3.50
with count = 6 opens the int box 6 and the float box 3.50, and Python's mixing
กฎจะยกระดับ int — ผลลัพธ์จะเป็น float21.0 ไม่ใช่ int 21.
ตัวอย่างทำแล้ว 1 (เครื่องคิดเงินคาเฟ่).count = int(input("Coffees? ")), แล้ว
print("Total:", count * 3.50). ที่ 6 แก้วกาแฟ โปรแกรมจะพิมพ์ Total: 21.0 — ซึ่งเป็น .0
ทำเครื่องหมายเป็น float เพราะ int * float ถูกแปลงเป็น float การสังเกตว่าผลลัพธ์มี
of an expression is unit 1.1's whole habit. Trace it the state way: input returns
the string "6"; int(...) opens a new box holding the int 6; the multiplication
makes a fresh float box 21.0; print shows it.
Worked example 2 (the classic accident, repaired). A banner printer joins a count
onto a message:
score = int(input("Score? "))
if score >= 80:
band = "A"
elif score >= 70:
band = "B"
elif score >= 60:
band = "C"
else:
band = "F"
print("Band:", band)
ข้อสังเกต: ค่า 79 ไม่จำเป็นต้องใช้ Band: B อีกต่อไป — การเข้าถึงบรรทัดนั้นพิสูจน์แล้วว่าคะแนนอยู่ต่ำกว่า
สังเกตว่า: elif score >= 70 ไม่จำเป็นต้องใช้ and score < 80 ด้วย — การเข้าถึงบรรทัดนั้น
line already proves the score is below 80. Trusting the fall-through like this is
สิ่งที่ทำให้โซ่สั้นลง: การทดสอบซ้ำทุกสิ่งเป็นสิ่งที่ผู้เริ่มต้นทำ ซึ่งยาวนานกว่าและผิดกว่า
version.
การชำระเงิน 5,000 ด้วยมือเป็นอาชีพ แต่เมื่อใช้ลูปจะเป็นโปรแกรม การทำซ้ำ
ทำซ้ำงาน: ลูป for จะวนผ่านลำดับที่ทราบล่วงหน้า; ลูป while จะทำงานจนกว่าจะมี
เงื่อนไขเป็นจริง คำถามในการออกแบบคือเสมอว่า: คุณรู้จำนวนรอบหรือไม่มี, หรือมี
a condition decide?
total = 0
for i in range(1, 101): # 1..100 — range stops BEFORE its end
total += i
print(total) # 5050
Use for when the trip count is known; use while when a condition decides. Every
while ต้องการสามสิ่งที่เห็นได้ในโค้ด: จุดเริ่มต้นของตัวแปร, เงื่อนไข,
และสิ่งภายในที่ทำให้เข้าใกล้การออก — มิฉะนั้นจะเป็น ลูปไม่สิ้นสุด
ลูป
ตารางติดตามสำหรับลูปแฟกทอเรียล
n = 5
factorial = 1
while n > 1:
factorial *= n
n -= 1 # the step toward exiting
print(factorial) # 120
ตัวอย่างที่คำนวณแล้ว 2 (การค้นหาด้วย break, ยกระดับ) หาเลขคูณของ
7 that is greater than 100 — the trip count is unknown, the condition decides:
n = 100
while True:
if n % 7 == 0:
break # found it — leave the loop now
n += 1
print(n) # 105
การติดตามสั้น: 100, 101, …, 104 ล้มเหลวในการทดสอบทั้งหมด; 105 ผ่านและ break
ออก. break ออกจากลูปก่อนกำหนด; continue ข้ามไปยังรอบถัดไป ทั้งสองอย่างนี้เป็น
readability tools — a loop that must scan until it finds something, then stop, reads
ดีที่สุดใน break. การเพิ่มยอดเงินสองเท่า: ที่ 5% ต่อปี ใช้เวลานานเท่าใด
1000 จะใช้เวลาถึง 2000?
balance = 1000.0
years = 0
while balance < 2000.0: # the condition itself is the goal
balance *= 1.05
years += 1
print(years, round(balance, 2)) # 15 2078.93
ห้าจุดถูกอัปเดต ฟังก์ชัน จัดแพ็กเกจงานไว้หลังชื่อเพื่อให้เขียน
five get updated. A function packages a job behind a name so it is written
กำหนด; การเรียกใช้งานดำเนินการ def กำหนด; การเรียกใช้งานดำเนินการ
defines; calling runs.
def total_price(count, unit=3.50):
"""Return the total for count items at unit price."""
return count * unit
print(total_price(6)) # 21.0
print(total_price(6, unit=4.0)) # 24.0
The definition gives a parameter (count, unit); the call supplies an
argument (6). A default value (unit=3.50) makes an argument optional.
return hands a value back and ends the call; printing is not returning — a
function without return returns None, and the caller that tries arithmetic on it
ได้รับ TypeError
def is_prime(n):
if n < 2:
return False
d = 2
while d * d <= n: # only test up to the square root
if n % d == 0:
return False # found a divisor — answer known, stop
d += 1
return True
print([p for p in range(2, 30) if is_prime(p)])
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
พฤติกรรมสองอย่างของฟังก์ชันมาพบกันที่นี่: การส่งกลับ return ล่วงหน้าจะจบการเรียกทันทีที่ทราบคำตอบ
เป็นสิ่งที่ทราบได้ล่วงหน้า (ไม่จำเป็นต้องใช้ตัวแปร flag) และขอบเขตของลูป d * d <= n มาจากการ
การหาอนุพันธ์ — หาก $n = a \times b$ พร้อมกับ $a \le b$ แล้ว จะได้ $a \le \sqrt{n}$ ดังนั้นการทดสอบเกิน $\sqrt{n}$
จะทดสอบตัวหารที่เคยเห็นมาแล้วใหม่ รันโค้ดนี้: รายการที่ได้จะเป็นจำนวนเฉพาะที่น้อยกว่า 30 พอดี
marks = [72, 85, 61]
marks.append(90) # [72, 85, 61, 90]
best = max(marks) # 90
average = sum(marks) / len(marks) # 77.0
การอ้างอิงร่วมกัน: สองชื่อ, ลิสต์เดียว
การกำหนดค่าไม่ได้คัดลอกข้อมูล: a = [1]; b = a; b.append(2) ทำให้ a ชี้ไปยัง [1, 2] — คือรายการ
ถูกแชร์กัน, แต่ชื่อนั้นไม่ใช่. การอ้างอิงร่วมกันนี้คือกล่องของหน่วย 1.1 อีกครั้ง, ตอนนี้
with two tags on one box, and it explains the next rule too: mutating a list while
วนลูปผ่านมันจะทำให้ข้ามบางองค์ประกอบ — ให้วนลูปผ่านสำเนา (for m in marks[:]) หรือสร้าง
รายการใหม่แทน
ร้านกาแฟปิดลง, ไฟดับ — และจำนวนรวมของเช้าจะอยู่ได้ก็ต่อเมื่อโปรแกรม
เขียนมันลงไดรฟ์แล้ว. ไฟล์ มีอายุยืนยาวกว่าโปรแกรม. with open(path) as f: opens, closes on exit, and reads text; open(path, "w") เขียน
(และเคลียร์ข้อมูลก่อน —อุบัติเหตุคลาสสิก)
with open("log.txt", "w") as f:
f.write("opened\n")
with open("log.txt") as f:
for line in f:
print(line.rstrip()) # rstrip removes the trailing newline
try:
with open("settings.txt") as f:
size = int(f.read().strip())
except FileNotFoundError:
size = 12 # no file yet: a sensible default
except ValueError:
size = 12 # the file holds "big", not a number
print("Text size", size)
Summary: with open(...) for both reading and writing; "w" empties first;
ข้อยกเว้นคือค่า — จับประเภทที่มีชื่อที่คุณคาดหวังไว้ fallback อย่างมีเหตุผล ปล่อยให้
the rest crash.
An assert that never fires is a passing test. Write the tests before you write the
body when you can — they are the contract made executable, and the loop above
(แดง → เขียว → refactor) คือนิสัยนั้นที่ดำเนินไปอย่างต่อเนื่อง