ข้ามไปเนื้อหา

วิธีคิดแบบนักวิทยาการคอมพิวเตอร์/Fruitful functions

จาก วิกิตำรา

บทที่ 5 Fruitful functions

[แก้ไข | แก้ไขต้นฉบับ]

5.1 Return values ฟังก์ชัน built-in บางตัวที่เราใช้ เช่น ฟังก์ชัน math จะได้ผลลัพธ์ออกมา การเรียกฟังก์ชันโดยการสร้างค่าใหม่ โดยปกติแล้วจะกำหนดให้เป็นตัวแปรหรือใช้ส่วนของ expression

e = math.exp(1.0)

height = radius * math.sin(angle)

แต่จนถึงตอนนี้ ไม่มีฟังก์ชันที่เราได้เขียนขึ้นและมีการ return ค่า

ในบทนี้เราตั้งใจที่จะเขียนฟังก์ชันที่มีการ return ค่า ซึ่งเราเรียกว่า fruitful functions ตัวอย่างแรกคือ area ซึ่ง return ค่าของพื้นที่ของวงกลมออกมา โดยให้ค่ารัศมีมา

import math

def area(radius):

temp = math.pi * radius**2

return temp

พวกเราได้เคยเห็น return statement มาก่อนแต่ใน fruitful function การ return statement รวมถึงการ return value ด้วย statement นี้ หมายความว่า return ค่าทันทีทันใดจากฟังก์ชันนี้และมีการ return value ตาม expression โดย expression ไม่มีกฎเกณฑ์และอยากที่จะอธิบาย ดังนั้นเราจึงควรเขียนฟังก์ชันนี้ให้ได้ใจความชัดเจน

def area(radius):

return math.pi * radius**2

ในอีกด้านหนึ่ง temporary variables เช่น temp บ่อยครั้งที่จะช่วยให้การแก้ไขจุดบกพร่องของโปรแกรมให้ง่ายขึ้น

บางครั้งสามารถใช้ประโยชน์กับ return statement ที่มากกว่า 1 โดยใช้ในแต่ละ brunch ของเงื่อนไข

def absoluteValue(x):

if x < 0:

return -x

else:

return x

ตั้งแต่ return statement เหล่านี้อยู่ในเงื่อนไขทางเลือก เพียงต้องการจะ execute ก็จะถูก execute และฟังก์ชันจะสิ้นสุดลงโดยปราศจากการ execute ใดๆ ตามลำดับ statement

โค้ดปรากฏหลังจาก return statement หรือที่ใดๆ ที่ flow of execution ไม่เคยเข้าถึง ถูกเรียกว่า dead code

ใน fruitful function มันเป็นความคิดที่ดีที่ทำให้แน่ใจว่าทุกๆ ทางเป็นไปได้ ถึงแม้โปรแกรมได้รับ return statement ตัวอย่างเช่น def absoluteValue(x):

if x < 0:

return -x

elif x > 0:

return x

โปรแกรมนี้ไม่ถูกต้อง เพราะถ้า x เกิดเป็น 0 ไม่มีเงื่อนไขที่เป็นจริง และฟังก์ชันจะจบลงโดยไม่มีการ return statement ในลักษณะนี้ return value คือค่าพิเศษ เรียกว่า None

>>> print absoluteValue(0)

None

ถึงจุดนี้คุณควรดูฟังก์ชันทั้งหมดและบอกว่าอะไรที่ต้องทำ ถ้าคุณกำลังทำแบบฝึกหัด คุณต้องเขียนฟังก์ชันเล็กๆ เมื่อคุณเขียนฟังก์ชันใหญ่ คุณอาจจะเริ่มรู้ว่ามันยากขึ้น โดยเฉพาะเวลา runtime และ semantic error

การจัดการกับโปรแกรมที่ซับซ้อนมากขึ้น พวกเราตั้งใจที่จะแนะนำเทคนิค ซึ่งเรียกว่า incremental development เป้าหมายของ incremental development คือ หลีกเลี่ยงการแก้ไขจุดบกพร่องที่ยาวนาน โดยเพิ่มโค้ดเล็กๆ เข้าไปเพื่อทดสอบ ณ เวลาหนึ่ง

เช่นตัวอย่าง สมมติว่าคุณต้องการหาค่าระยะทางระหว่าง จุดสองจุด โดยมีพิกัด คือ (x1,y1) และ (x2,y2) โดยสูตรระยะทางคือ

ขั้นแรกให้พิจารณาว่า ฟังก์ชัน distance ใน python ควรมีลักษณะอย่างไร อะไรคือ input (parameters) และอะไรคือ output (return value)

ใน case นี้ จุดสองจุดคือ input ซึ่งสามารถแทนโดยใช้ 4 พารามิเตอร์ return value คือ ระยะทาง ซึ่งเป็นค่า floating-point เมื่อเรียบร้อยแล้วเราสามารถเขียนฟังก์ชันคร่าวๆ ได้ดังนี้

def distance(x1, y1, x2, y2):

return 0.0

เห็นอย่างชัดเจนว่าฟังก์ชันนี้ไม่มีการคำนวณระยะทาง มันจะได้ค่าเป็น 0 เสมอ แต่เป็น syntac ที่ถูกต้อง และมันจะ run หมายถึงว่าพวกเราสามารถทดสอบมันก่อนที่เราจะเพิ่มความซับซ้อนมากขึ้นไป

การทดสอบฟังก์ชันใหม่ เราเรียกมันโดยใส่ค่าตัวอย่างลงไป

>>> distance(1, 2, 4, 6)

0.0 เมื่อเราเลือกค่าเหล่านี้ ระยะทางแนวนอนคือ 3 และระยะทางแนวตั้ง คือ 4 ผลลัพธ์ที่ได้คือ 5 เมื่อทดสอบฟังก์ชันแล้ว มันเป็นประโยชน์ที่รู้คำตอบที่ถูกต้อง

ตรงจุดนี้เราแน่ใจว่า syntac ของฟังก์ชันถูกต้อง และเราสามารถเพิ่มโค้ดเข้าไปได้อีก หลังจากที่เกิดการเปลี่ยนแปลงขึ้นเราจะทำการทดสอบฟังก์ชันอีกครั้ง ถ้าเกิด error ตรงจุดใด พวกเรารู้ว่าต้องเป็นบรรทัดสุดท้ายที่ได้เพิ่มเข้าไป

ในการคำนวณด้านตรรกะ ขั้นตอนแรกคือ หาค่าความต่างของ x2-x1 และ y2-y1 เราเก็บค่าเหล่านี้ไว้ใน temporary variables ชื่อ dx และ dy และพิมพ์ค่าพวกมัน

def distance(x1, y1, x2, y2):

dx = x2 - x1

dy = y2 - y1

print "dx is", dx

print "dy is", dy

return 0.0

ถ้าฟังก์ชันกำลังทำงาน ผลลัพธ์ที่ได้ควรเป็น 3 และ 4 เรารู้ว่าฟังก์ชันนี้ได้รับค่าพารามิเตอร์ที่ถูกต้องและการคำนวณลำดับแรกถูกต้อง ถ้าไม่เป็นเช่นนั้น ก็มีเพียง 2-3 บรรทัดที่ต้องตรวจสอบ

ถัดไปเราคำนวณผลบวกของกำลังสองของ dx และ dy

def distance(x1, y1, x2, y2):

dx = x2 - x1

dy = y2 - y1

dsquared = dx**2 + dy**2

print "dsquared is: ", dsquared

return 0.0

สังเกตว่าเราเอา print statement ที่เราเขียนในขั้นตอนก่อนหน้านี้ออกไป ลักษณะโค้ดแบบนี้เรียกว่า scaffolding เพราะมันช่วยเหลือในการสร้างโปรแกรม แต่ไม่ใช่ส่วนของผลขั้นสุดท้าย

เราควร run โปรแกรมตอนนี้ และ ตรวจสอบผลลัพธ์ ซึ่งควรจะเป็น 25

ท้ายสุด ถ้าเรา import module ของ math เขาไป เราสามารถใช้ฟังก์ชัน sqrt เพื่อคำนวณและ return ผลลัพธ์ออกมา

def distance(x1, y1, x2, y2):

dx = x2 - x1

dy = y2 - y1 dsquared = dx**2 + dy**2

result = math.sqrt(dsquared)

return result

ถ้าการทำงานถูกต้อง คุณจะได้ผลลัพธ์ออกมา ไม่เช่นนั้น คุณอาจจะต้องการพิมพ์ค่าของผลลัพธ์ก่อนจะ retuen statement

เมื่อคุณเริ่มไปไกลควรจะเพิ่มโค้ดเพียง 1 หรือ 2 บรรทัดเท่านั้น เมื่อคุณได้รับประสบการณ์มากขึ้น คุณอาจจะหาวิธีการเขียนด้วยตัวคุณเอง และแก้ไขจุดบกพร่องที่ใหญ่กว่าเดิมได้ เช่นเดียวกันกระบวนการ incremental development ช่วยประหยัดเวลาในการแก้ไขจุดบกพร่องได้

มุมมองทีสำคัญของกระบวนการนี้คือ

- เมื่อเริ่มเขียนโปรแกรม ควรเขียนเพิ่มไปทีละน้อย ถ้าเกิด error ที่จุดใด เราจะสามารถรู้ได้แน่ชัดว่าเกิดขั้นที่จุดไหน

- ใช้ temporary variables เพื่อเก็บค่าตัวกลางไว้ ดังนั้นคุณสามารถแสดงผลออกมาและตรวจสอบมัน

- ทันทีที่โปรแกรมกำลังทำงาน คุณอาจต้องการลบบางส่วนของ scaffolding หรือ การรวม statement หลายๆอันให้เป็นอันเดียวแล้วรวมกับ expresion อีกที แต่ไม่ควรทำให้โปรแกรมอ่านยาก

อย่างที่คุณควรคาดไว้ในตอนนี้ คุณสามารถเรียกหนึ่งฟังก์ชันจากในฟังก์ชันอื่นได้ ความสามารถนี้เรียกว่า composition

ดังเช่นตัวอย่าง เราจะเขียนฟังก์ชันที่มี 2 ประเด็น ศูนย์กลางของฟังก์ชันที่ชี้ไปยังเส้นรอบวง และคำนวณพื้นที่ของวงกลม

สมมติให้จุดศูนย์กลางถูกเก็บในตัวแปร xc และ yc และจุดเส้นรอบวงเก็บใน xp และ yp ขั้นแรกคือ หารัศมีของวงกลม ซึ่งคือระยะทางระหว่างจุดสองจุด โชคดีที่มีฟังก์ชัน distance ที่ทำไว้แล้ว

radius = distance(xc, yc, xp, yp)

ขั้นที่สองคือ หาพื้นที่ของวงกลมซึ่งมีรัศมี และ return ค่า

result = area(radius)

return result

นำมารวมกันในฟังก์ชันเราจะได้

def area2(xc, yc, xp, yp):

radius = distance(xc, yc, xp, yp)

result = area(radius)

return result

เราเรียกฟังก์ชันนี้ว่า area2 เพื่อแยกออกจากฟังก์ชัน area ที่ถูกอ้างอิงถึงก่อนหน้านี้ หนึ่งฟังก์ชันที่ได้ให้ชื่ออยู่ใน module ที่ได้ให้ไว้เท่านั้น

ตัวแปรชั่วคราว radius และ result มีประโยชน์ในการพัฒนาและการแก้ไขข้อบกพร่อง แต่ทันทีที่โปรแกรมกำลังทำงาน เราสามารถทำให้มันรัดกุมโดยการเรียบเรียงฟังก์ชันที่ถูกเรียก

def area2(xc, yc, xp, yp):

return area(distance(xc, yc, xp, yp))

ฟังก์ชันสามารถ return ค่า boolean ซึ่งสะดวกในการซ่อนการทดสอบที่ซับซ้อนภายในฟังก์ชัน ตัวอย่าง

def isDivisible(x, y):

if x % y == 0:

return True

else:

return False

ชื่อของฟังก์ชัน คือ isDivisible มันเป็นธรรมดาที่จะให้ชื่อของฟังก์ชัน boolean ซึ่งดูเหมือนคำถาม yes/no โดย isDivisible ให้ค่า true หรือไม่ก็ false เพื่อบ่งชี้ว่า x หารด้วย y ลงตัวหรือไม่

เราสามารถทำให้ฟังก์ชันนี้รัดกุมขึ้น ด้วยการนำข้อดีของข้อเท็จจริงที่เงื่อนไขของ if statement โดยตัวมันเป็น boolean expression เราสามารถ return มันโดยตรง หลีกเลี่ยง if statement ทั้งหมด

def isDivisible(x, y):

return x % y == 0

ส่วนนี้แสดงถึงฟังก์ชันใหม่

>>> isDivisible(6, 4)

False

>>> isDivisible(6, 3)

True

ฟังก์ชัน Boolean ถูกใช้บ่อยใน statement เงื่อนไข

if isDivisible(x, y): print "x is divisible by y" else: print "x is not divisible by y" มันอาจเป็นการทดสอบที่จะเขียนบางสิ่ง เช่น

if isDivisible(x, y) == True:

แต่การเปรียบเทียบแบบพิเศษไม่จำเป็น

ถึงตอนนี้คุณได้ยินเพียง subset ขนาดเล็กของ python แต่คุณอาจสนใจที่จะรู้ว่า subset นี้คือ complete programming language ซึ่งหมายถึงสิ่งใดๆ ที่สามารถคำนวณ สามารถแสดงออกในภาษานี้ โปรแกรมใดที่เคยเขียนสามารถนำมาเขียนขึ้นใหม่โดยใช้เพียงรูปแบบของภาษาที่คุณได้เรียนถึงตอนนี้

การให้สิทธินั้นคือ แบบฝึกหัดที่สำคัญที่จะนำไปสู่ความสำเร็จ โดยหนึ่งในนักวิทยาศาสตร์คอมพิวเตอร์คนแรก (มีการถกเถียงว่าเป็นนักคณิตศาสตร์แต่นักวิทยาศาสตร์คอมพิวเตอร์ส่วนใหญ่เริ่มจากการเป็นนักคณิตศาสตร์) ดังนั้น มันถูกรู้จากวิทยานิพนธ์ของ Turing ถ้าคุณได้รับแนวทางในทฤษฎีของการคำนวณ คุณมีโอกาสที่จะเห็นการพิสูจน์

ให้ความคิดของคุณสามารถทำอะไรกับเครื่องมือที่คุณได้เรียนมาจนถึงตอนนี้ เราจะหาค่าฟังก์ชัน recursively defined mathematical ส่วนน้อย โดย recursive definition จะเหมือนกับ circular definition ในความรู้สึก definition บรรจุการอ้างอิงในสิ่งที่ถูกระบุ circular definition ไม่ถูกใช้ประโยชน์อย่างแท้จริง

Frabjuous : คำขยายที่ใช้อธิบายบางสิ่งคือ frabjuous

ถ้าคุณเห็น definition ในพจนานุกรม คุณอาจรู้สึกรำคาญ ในทางตรงกันข้าม ถ้าคุณหา definition ของฟังก์ชัน factorial ในคณิตศาสตร์ คุณอาจได้บางสิ่งเช่นนี้

0! = 1

n! = n(n ¡ 1)!

Definition นี้พูดถึง factorial ของ 0 คือ 1 และ factorial ของค่าใดๆ คือ n คูณด้วย factorial ของ n – 1

ดังนั้น 3! คือ 3คูณ 2! ซึ่งคือ 2 คูณ 1! ซึ่งคือ 1 คูณ 0 ! การวางทั้งหมดเข้าด้วยกัน 3! เท่ากับ 3 คูณ 2 คูณ 1 คูณ 1 ซึ่งคือ 6

ถ้าคุณสามรถเขียนบางสิ่งของ recursive definition คุณสามารถเขียนโปแกรม python ในการหาค่ามันได้อย่างปกติ ขั้นตอนแรกคือ ตัดสินใจว่าพารามิเตอร์ของฟังก์ชันคืออะไร คุณควรตัดสินใจว่า พารามิเตอร์รับค่าตัวเดียว

def factorial(n):

ถ้า agrument เกิดเป็น 0 ทั้งหมดเราต้องทำให้ return 1

def factorial(n):

if n == 0:

return 1

และนี้คือส่วนที่สนใจ พวกเราต้องทำการเรียก recursive ที่จะหา factorial ของ n – 1 และคูณมันด้วย n

def factorial(n):

if n == 0:

return 1

else:

recurse = factorial(n-1)

result = n * recurse

return result

flow of execution สำหรับโปรแกรมนี้เหมือนกับ flow of countdown ใน section 4.9 ถ้าพวกเราเรียก factorial มีค่า 3 ตั้งแต่ 3 ไม่ใช่ 0 เรารับค่าส่วนที่สองและคำควณ factorial ของ n -1

ตั้งแต่ 2 ไม่ใช่ 0 เรารับค่าส่วนที่สองและคำควณ factorial ของ n -1

ตั้งแต่ 1 ไม่ใช่ 0 เรารับค่าส่วนที่สองและคำควณ factorial ของ n -1

ตั้งแต่ 0 คือ 0 เรารับค่าในส่วนแรก และ return ค่า 1 ปราศจากการเรียก recursive ใดๆ มากกว่านี้

Return value (1) คือ คูณด้วย n ซึ่งคือ 1 และผลลัพธ์ return ค่าออกมา

Return value (1) คือ คูณด้วย n ซึ่งคือ 2 และผลลัพธ์ return ค่าออกมา

Return value (2) คือ คูณด้วย n ซึ่งคือ 3 และผลลัพธ์ 6 กลายเป็น return value ของฟังก์ชันที่ถูกเรียกตอนเริ่มกระบวนการทั้งหมด นี้คือ stack diagram ซึ่งดูเหมือนการเรียงลำดับของการเรียกฟังก์ชัน

Return value ถูกแสดงโดยผ่านการดันจาก stack ในแต่ละกรอบ return value คือค่าผลลัพธ์ ซึ่งคือ ผลของ n และ recurse

สังเกตว่าในกรอบสุดท้าย local variables ซึ่งคือ recurse และ result ไม่คงอยู่ เพราะส่วนที่สร้างพวกมันไม่ได้ execute

ที่จะกล่าวต่อไป flow of execution เป็นทางหนึ่งที่จะอ่านโปรแกรม แต่มันสามารถซับซ้อนได้อย่างรวดเร็ว และทางเลือกที่เราเรียกว่า leap of faith เมื่อคุณมาถึง function call แทนที่จะตาม flow of execution คุณยอมรับว่าฟังก์ชันทำงานอย่างถูกต้อง และแสดงค่าอย่างเหมาะสม

ที่จริงคุณกำลังฝึกซ้อม leap of faith เมื่อคุณใช้ฟังก์ชัน built-in เมื่อคุณเรียก math.cos หรือ math.exp คุณไม่ได้พิจารณาการทำให้เกิดผลของฟังก์ชันนั้น คุณแค่ยอมรับว่ามันทำงาน เนื่องจากคนที่เขียน built-in libraries เป็นโปรแกรมที่ดี

ที่เหมือนกันคือ ถูกต้องเมื่อคุณเรียกฟังก์ชันของคุณเอง ตัวอย่าง ในตอนที่ 5.4 เราเขียนฟังก์ชันที่เรียกว่า isDivisible ที่พิจารณา ไม่ว่าอย่างไรก็ตามที่ตัวเลขหนึ่ง ตัวที่ถูกหารลงตัวด้วยอีกตัวเลขหนึ่ง ครั้งหนึ่งเราได้ทำให้เราแน่ใจแล้วว่าฟังก์ชันนี้ถูกต้อง ด้วยการทดสอบและการพิจารณาโค้ด เราสามารถใช้ฟังก์ชันโดยไม่ต้องมองดูโค้ดอีกครั้ง

ความถูกต้องที่เหมือนกันของโปรแกรม recursive เมื่อคุณไปถึง recursive call แทนที่จะตาม flow of execution คุณควรยอมรับว่า recursive call ทำงานได้ (ให้ผลลัพธ์ที่ถูกต้อง) และหลังจากนั้นถามตัวคุณเอง “เป็นที่เข้าใจว่าฉันสามารถหา factorial ของ n -1 ฉันสามารถหา factorial ของ nได้หรือไม่” ในกรณีนี้คุณสามารถทำได้โดยการคูณด้วย n แน่นอน มันแปลกเล็กน้อยที่จะยอมรับว่าฟังก์ชันสามารถที่จะทำงานได้อย่างถูกต้อง เมื่อคุณไม่ได้เขียนมัน นี่เป็นเหตุที่ทำให้มันถูกเรียกว่า leap of faith

ในตัวอย่างที่ผ่านมา เราได้ใช้ตัวแปรชั่วคราวในการขยายความขั้นตอนและทำให้โค้ดง่ายต่อการ debug มากขึ้น แต่เราสามารประหยัดบรรทัดได้

def factorial(n):

if n == 0:

return 1

else:

return n * factorial(n-1)

จากนี้ไปเราจะเน้นที่จะใช้รูปแบบที่สั้นกระชับ แต่เราแนะนำให้คุณใช้รูปแบบที่ชัดเจน ในระหว่างที่คุณกำลังพัฒนาโค้ด เมื่อมันสามารถทำงานได้ คุณสามารถทำให้มันแน่นขึ้น ถ้าคุณรู้สึกฉลาด

หลังจาก factorial ตัวอย่างง่ายที่สุดของ recursively ที่กำหนดฟังก์ชัน mathematicalคือ Fibonacci ซึ่งมีคำนิยามดังนี้

bonacci(0) = 1

bonacci(1) = 1

bonacci(n) = bonacci(n - 1) + bonacci(n - 2);

แปลงเป็น python มันดูเหมือนดังนี้

def fibonacci (n):

if n == 0 or n == 1:

return 1

else:

return fibonacci(n-1) + fibonacci(n-2)

ถ้าคุณลองตาม flow of execution ที่นี่ ค่าของ n ที่เล็กมาก แต่ตาม leap of faith ถ้าคุณสมมติว่า ทั้งสอง recursive call ทำงานถูกต้อง แล้วมันชัดเจนที่คุณได้ผลลัพธ์ที่ถูกต้องด้วยการเพิ่มมันเข้าด้วยกัน

อะไรจะเกิดขึ้นถ้าเราเรียก factorial และให้argument เป็น 1.5

>>> factorial (1.5)

RuntimeError: Maximum recursion depth exceeded

มันดูเหมือน infinite recursion แต่มันเป็นแบบนั้นได้อย่างไร มี base-case เมื่อ n==0 ปัญหาคือ ค่าของ n หลีกเลี่ยง base case ใน recursive call ครั้งแรก ค่าของ n คือ 0.5 ถัดไปมันเป็น -0.5 จากนี้มันจะมีค่าน้อยลง แต่จะไม่เป็น 0

เรามีอยู่สองทางเลือก เราสามารถลองกล่าวสรุปฟังก์ชัน factorial ที่ทำงานกับตัวเลขทศนิยม หรือเราสามารถสร้าง factorial ตรวจสอบรูปแบบพารามิเตอร์ของมันเอง ทางเลือกแรกถูกเรียกว่า ฟังก์ชัน gamma และมันห่างไกลจากของเขตของหนังสือเล่มนี้ ดังนั้นเราจะไปยังทางเลือกที่สอง

เราสามารถใช้ฟังก์ชัน built-in isinstance เพื่อยืนยันความถูกต้องของรูปแบบของพารามิเตอร์

ระหว่างที่เราอยู่ที่ฟังก์ชัน isinstance เราแน่ใจได้ว่าพารามิเตอร์เป็นบวก def factorial (n):

if not isinstance(n, int):

print "Factorial is only defined for integers."

return -1

elif n < 0:

print "Factorial is only defined for positive integers."

return -1

elif n == 0:

return 1

else:

return n * factorial(n-1)

ตอนนี้เรามี 3 baes case อย่างแรกจับที่ไม่เป็น integer อย่างที่สองจับ integer ที่เป็นลบ ในทั้งสองกรณี โปรแกรมแสดงข้อความ error และ return ค่าพิเศษ -1 เพื่อบ่งบอกว่าบางอย่างผิด

>>> factorial ("fred")

Factorial is only defined for integers.

-1

>>> factorial (-2)

Factorial is only defined for positive integers.

-1

ถ้าเราผ่านการตรวจสอบทั้งสอง เราจะรู้ว่า n นั้นเป็น integer ที่เป็นบวก และเราสามารถตรวจสอบการสิ้นสุดของ recursive

โปรแกรมนี้สาธิตแบบแผนบางครั้งก็เรียกว่า guardian เงื่อนไขสองอย่างแรกทำงานเป็น guardians คอยคุ้มครองโค้ดที่ตามหลังค่าที่อาจเป็นสาเหตุของข้อผิดพลาด guardians ทำให้มันเป็นไปได้ในความถูกต้องของโค้ด

fruitful function: A function that yields a return value.

return value: The value provided as the result of a function call.

temporary variable: A variable used to store an intermediate value in a complex calculation.

dead code: Part of a program that can never be executed, often because it appears after a return statement.

None: A special Python value returned by functions that have no return statement, or a return statement without an argument.

incremental development: A program development plan intended to avoid debugging by adding and testing only a small amount of code at a time.

scaffolding: Code that is used during program development but is not part of the final version.

guardian: A condition that checks for and handles circumstances that might cause an error.