เวลาใช้ if ในภาษาไพธอน บ่อยครั้งที่เราจะใช้ and และ or เพื่อรวมเงื่อนไข ๒ ข้อขึ้นไปเข้าด้วยกัน
หลักการโดยพื้นฐานอธิบายไว้ใน
https://phyblas.hinaboshi.com/tsuchinoko06 แต่มีรายละเอียดเพิ่มเติมเล็กๆน้อยๆเกี่ยวกับการใช้ and และ or ที่ไม่ได้กล่าวถึงในนั้น และหลายคนอาจจะยังไม่รู้ จึงขอเขียนถึงไว้ในหน้านี้
ลำดับก่อนหลังนั้นสำคัญ ในการใช้งานโดยทั่วไปบางคนอาจไม่ได้ใส่ใจลำดับก่อนหลัง เพราะผลลัพธ์ที่ได้ยังไงก็เหมือนกัน เช่น
a = 3
b = 5
if(a>4 or b>4):
print('มีตัวที่มากกว่า 4')
แบบนี้จะสลับเป็น b>4 or a>4 ก็ได้ผลไม่ต่างกัน อย่างไรก็ตาม จริงๆแล้วการทำงานที่เกิดขึ้นภายในนั้นต่างกัน
ที่จริงแล้วเมื่อมีการใช้ and หรือ or จะมีการพิจารณาความจริงเท็จไล่จากตัวซ้ายก่อน ถ้าผลจริงเท็จถูกตัดสินไปแล้ว ตัวทางขวาจะไม่ถูกนำมาคิดแล้ว
หมายความว่าถ้าใช้ or แล้วพบว่าตัวซ้ายเป็นจริง ยังไงทั้งหมดก็เป็นจริงแน่นอนแล้วไม่ว่าตัวขวาจะเป็นอะไร จึงไม่มีการคิดทางขวาต่อ ถ้าทางขวาเป็นฟังก์ชันก็จะไม่มีการทำงานเกิดขึ้น
และถ้าเป็น and แล้วตัวซ้ายเป็นเท็จ แบบนี้ต่อให้ตัวขวาเป็นอย่างไรผลก็เป็นเท็จแน่นอนแล้วจึงไม่มีการทำอะไรกับตัวขวาต่อ
เพื่อให้เห็นภาพชัด ลองสมมุติฟังก์ชันง่ายๆที่จะมีการ print อะไรทุกครั้งที่มีการเรียกใช้ ก่อนที่จะคืนค่าออกมา
def f(x):
if(x%3==0):
print('x=%d หาร 3 ลงตัว'%x)
else:
print('x=%d หาร 3 ไม่ลงตัว'%x)
return x%3==0
if(f(x=5) or f(x=6)):
print('มี x ที่หาร 3 ลงตัว')
ได้
x=5 หาร 3 ไม่ลงตัว
x=6 หาร 3 ลงตัว
มี x ที่หาร 3 ลงตัว
แต่หากเปลี่ยนเป็น
if(f(x=6) or f(x=5)):
print('มี x ที่หาร 3 ลงตัว')
จะได้
x=6 หาร 3 ลงตัว
มี x ที่หาร 3 ลงตัว
นั่นคือเมื่อพบว่าตัวแรกคือ x=6 นั้นหาร 3 ลงตัวดีแล้ว ตัวทางขวาคือ x=5 ก็ไม่ถูกนำมาคิดอีก ซึ่งจะเห็นได้ว่าไม่มีการ print กรณี x=5 ออกมา
จะเรียงกันกี่ตัวก็ได้ ถ้าเจอสักตัวที่เป็นจริงก็จะหยุดทันที
if(f(x=7) or f(x=8) or f(x=9) or f(x=10)):
print('มี x ที่หาร 3 ลงตัว')
จะได้ว่าหยุดหลังเจอ x=9
x=7 หาร 3 ไม่ลงตัว
x=8 หาร 3 ไม่ลงตัว
x=9 หาร 3 ลงตัว
มี x ที่หาร 3 ลงตัว
ในทางกลับกัน ถ้าใช้ and แล้วเจอตัวที่เป็นเท็จเมื่อไหร่ก็จะหยุดทันที
if(f(x=6) and f(x=5) and f(x=4)):
print('ทุกตัวหาร 3 ลงตัว')
else:
print('มีตัวที่หาร 3 ไม่ลงตัว')
ได้
x=6 หาร 3 ลงตัว
x=5 หาร 3 ไม่ลงตัว
มีตัวที่หาร 3 ไม่ลงตัว
หากเราใส่ใจแค่ผลลัพธ์สุดท้าย ก็อาจจะไม่ต้องใส่ใจเรื่องลำดับว่าจะวางอะไรไว้ซ้ายหรือขวาก็ได้
แต่หากสิ่งที่อยู่ในนั้นเป็นฟังก์ชันที่มีการทำอะไรบางอย่างข้างในไปด้วยนอกเหนือจากแค่คืนค่า อาจส่งผลอะไรบางอย่างที่ต่างกันได้ จึงต้องระวัง
และอีกเรื่องหนึ่งคือ มันอาจส่งผลถึงเวลาที่ถูกใช้ในการคำนวณของโปรแกรม
อย่าง สมมุติเรามีเงื่อนไขหลายอย่าง แล้วต้องการให้ถ้าเป็นจริงแค่เงื่อนไขใดหนึ่งก็พอแล้ว แบบนี้ควรเอาเงื่อนไขที่คำนวณได้เร็วไว้ก่อน ส่วนเงื่อนไขที่คำนวณช้าเอาไว้ทีหลัง
เช่น สมมุติว่า x เป็นเลขตัวนึง และ lis เป็นลิสต์อะไรสักอย่างที่บรรจุตัวเลขไว้มากมาย
if(x==0 or x in lis):
การดูว่า x เท่ากับ 0 หรือไม่นั้นใช้เวลาน้อยกว่าการดูว่า x เป็นสมาชิกในลิสต์หรือเปล่ามาก ดังนั้นให้ x==0 ไว้ทางซ้ายน่าจะดีกว่า
หรือลองยกตัวอย่างที่เทียบกับชีวิตจริง เช่นเรากำลังสงสัยว่าคอมเสียหรือไม่ ถ้าเสียจะส่งไปให้ช่างคอมซ่อม
สมมุติว่าการตรวจว่า cpu เสียหรือเปล่าใช้เวลาน้อยกว่า ram และการตรวจ gpu ใช้เวลานานที่สุด งั้นเราก็ควรจะตรวจ cpu ก่อน แล้วตามด้วย ram
if(cpu_เสียหรือ(คอม) or ram_เสียหรือ(คอม) or gpu_เสียหรือ(คอม)):
ส่งไปให้ช่างซ่อม(คอม)
else:
เปิดคอมเล่นเกม(คอม)
and และ or ไม่ต้องใช้แค่กับ if แม้กรณีส่วนใหญ่จะใช้กับ if แต่บางครั้งก็เจอในสถานการณ์อื่น
เช่นถ้าจะแค่ใช้ให้หาค่าเก็บไว้ในตัวแปร หรือว่าจะ print ออกมาเลยก็ได้
a = 2
x = (a>3 or a<1)
print(x) # ได้ False
print(a<3 and a>1) # ได้ True
กรณีแบบนี้ or อาจคล้ายกับการใช้ | ส่วน and คล้ายกับการใช้ & เพียงแต่ and และ or มีลำดับความสำคัญสูงกว่า จึงไม่ต้องใส่วงเล็บ แต่ | และ & ต้องใส่
x = ((a>3) | (a<1))
print(x) # ได้ False
print((a<3) & (a>1)) # ได้ True
ผลของ and และ or ไม่ได้มีแต่ True และ False ถ้าใช้ and จะได้ค่าตัวซ้ายสุดที่มีค่าความจริงเป็นเท็จ (เช่น False, None, 0 หรือลิสต์ว่าง) แต่หากไม่มีที่เป็นเท็จเลยจะให้ค่าตัวขวาสุด
ตัวอย่าง
print(0 and False and None) # ได้ 0
print(1 and 0 and False and None) # ได้ 0
print(False and [] and 0) # ได้ False
print(1 and None and 0) # ได้ None
print(1 and 2 and 3 and 0) # ได้ 0
print(1 and 2 and 3) # ได้ 3
print(1 and 3 and 2) # ได้ 2
ถ้าเป็น or จะได้ค่าตัวซ้ายสุดที่มีค่าความจริงเป็นจริง แต่ถ้าไม่มีที่เป็นจริงเลยจะได้ตัวขวาสุด
print(0 or 1 or 2) # ได้ 1
print(0 or 2 or 1) # ได้ 2
print([] or None or 0) # ได้ 0
print([] or 0 or None) # ได้ None
นี่เป็นหลักการทำงานโดยละเอียดจริงๆของ and และ or
ใช้ and หรือ or แทน if ได้ จากคุณสมบัติที่ว่ามา บางครั้งก็อาจนำมาใช้แทน if ได้ เช่น
เนื่องจาก and จะทำตัวทางขวาต่อเมื่อตัวทางซ้ายเป็นจริง ดังนั้นหากเขียนแบบนี้
x>1 and print("x มากกว่า 1")
แบบนี้มีค่าเท่ากับ
if(x>1): print("x มากกว่า 1")
ส่วน or จะทำตัวทางขวาต่อเมื่อทางซ้ายเป็นเท็จ ดังนั้นหากเขียนแบบนี้
x>3 or print("x ไม่มากกว่า 3")
จะเท่ากับเขียนว่า
if(not x>3): print("x ไม่มากกว่า 3")
อย่างไรก็ตาม เมื่อพิจารณาเรื่องความง่ายในการเข้าใจแล้ว โอกาสที่จะเขียนแบบนี้อาจมีไม่มากนัก เพราะเข้าใจยากกว่าการใช้ if ธรรมดา แม้อาจทำให้การเขียนดูสั้นลงก็ตาม