ห้องเรียนรู้ Karinoya

คุณวุฒิ · แล็บสอบผ่าน Cloud / AI / Python

ชนิดข้อมูลและสตริงของ Python

อ่านโจทย์และคำอธิบายเป็นไทยได้ ส่วนบทบรรยาย (บทความอธิบาย) มีเฉพาะฉบับภาษาญี่ปุ่นเท่านั้น

ดูฉบับภาษาญี่ปุ่น (มีบทบรรยาย) →

ข้อ 1 | ตำราหลัก

หนังสือที่เป็นตำราหลักของการสอบวัดพื้นฐานวิศวกร Python 3 (Python 3 エンジニア認定基礎試験) คือเล่มใด

  1. 『Pythonチュートリアル』(คู่มือ Python) จัดพิมพ์โดยオライリー・ジャパン (O'Reilly Japan)
  2. 『あたらしいデータ分析の教科書』(ตำราวิเคราะห์ข้อมูลเล่มใหม่) จัดพิมพ์โดย翔泳社 (Shoeisha)
  3. 『Pythonデータ分析 実践ハンドブック』(คู่มือปฏิบัติการวิเคราะห์ข้อมูลด้วย Python) จัดพิมพ์โดยインプレス (Impress)
  4. 『Python実践レシピ』(สูตรปฏิบัติ Python) จัดพิมพ์โดย技術評論社 (Gijutsu-Hyoron-sha)
คำตอบA. 『Pythonチュートリアル』(คู่มือ Python) จัดพิมพ์โดยオライリー・ジャパン (O'Reilly Japan)

ตำราหลักของการสอบวัดพื้นฐานคือ『Pythonチュートリアル』(คู่มือ Python) ของオライリー・ジャパン (O'Reilly Japan) หน้าเว็บทางการระบุว่าตั้งแต่วันที่ 1 กันยายน 2021 จะอ้างอิงจากฉบับพิมพ์ครั้งที่ 4 ขอบเขตการสอบก็เปิดเผยตามหมายเลขบทและชื่อบทของหนังสือเล่มนี้ การเตรียมตัวจึงเป็นการทำความเข้าใจเนื้อหาของหนังสือเล่มนี้ตามน้ำหนักของแต่ละบท『Python実践レシピ』(สูตรปฏิบัติ Python) ของ技術評論社 (Gijutsu-Hyoron-sha) เป็นตำราหลักของการสอบภาคปฏิบัติ『Pythonによるあたらしいデータ分析の教科書』(ตำราวิเคราะห์ข้อมูลเล่มใหม่ด้วย Python) ของ翔泳社 (Shoeisha) เป็นตำราหลักของการสอบวิเคราะห์ข้อมูล และ『Pythonデータ分析 実践ハンドブック』(คู่มือปฏิบัติการวิเคราะห์ข้อมูลด้วย Python) ของインプレス (Impress) เป็นตำราหลักของการสอบภาคปฏิบัติวิเคราะห์ข้อมูล ทั้งหมดเป็นตำราของการสอบอื่นที่จัดโดยสมาคมเดียวกัน หากสลับตำรากันจะกลายเป็นการเรียนนอกขอบเขตไปเรื่อย ๆ จึงควรตรวจสอบให้แน่ใจตั้งแต่แรก

ข้อ 2 | บทที่มีจำนวนมากที่สุด

ในขอบเขตการสอบวัดพื้นฐาน บทใดในตำราหลักที่มีจำนวนข้อสอบออกมากที่สุด

  1. บทที่ 5 「データ構造」(โครงสร้างข้อมูล)
  2. บทที่ 4 「制御構造ツール」(เครื่องมือโครงสร้างควบคุม)
  3. บทที่ 3 「気楽な入門編」(เกริ่นนำแบบสบาย ๆ)
  4. บทที่ 8 「エラーと例外」(ข้อผิดพลาดและข้อยกเว้น)
คำตอบB. บทที่ 4 「制御構造ツール」(เครื่องมือโครงสร้างควบคุม)

บทที่มีจำนวนมากที่สุดคือบทที่ 4 「制御構造ツール」(เครื่องมือโครงสร้างควบคุม) ซึ่งได้รับการจัดสรร 9 ข้อจากทั้งหมด 40 ข้อ รองลงมาคือบทที่ 5 「データ構造」(โครงสร้างข้อมูล) 7 ข้อ และบทที่ 3 「気楽な入門編」(เกริ่นนำแบบสบาย ๆ) 6 ข้อ ส่วนบทที่ 8 「エラーと例外」(ข้อผิดพลาดและข้อยกเว้น) มี 4 ข้อ เพียงบทที่ 3, 4 และ 5 รวมกันก็ได้ 22 ข้อ เกินครึ่งหนึ่งของทั้งหมดแล้ว ดังนั้นการจัดสรรเวลาเรียนให้หนักไปที่ 3 บทนี้จึงสมเหตุสมผล โดยเฉพาะบทที่ 4 ซึ่งครอบคลุมคำสั่ง for และการนิยามฟังก์ชัน หากเลื่อนไปทีหลังจะแก้ไขไม่ทัน

ข้อ 3 | สัดส่วนแยกตามบท

ในขอบเขตการสอบวัดพื้นฐาน สัดส่วนที่บทที่ 4 「制御構造ツール」(เครื่องมือโครงสร้างควบคุม) ครองอยู่คือเท่าใด

  1. 17.5%
  2. 10.0%
  3. 22.5%
  4. 15.0%
คำตอบC. 22.5%

บทที่ 4 「制御構造ツール」(เครื่องมือโครงสร้างควบคุม) มี 9 ข้อจากทั้งหมด 40 ข้อ คิดเป็นสัดส่วน 22.5% ซึ่งมากที่สุดในแต่ละบท รองลงมาคือบทที่ 5 「データ構造」(โครงสร้างข้อมูล) 7 ข้อ คิดเป็น 17.5% ส่วน 15.0% ตรงกับบทที่ 3 「気楽な入門編」(เกริ่นนำแบบสบาย ๆ) 6 ข้อ และ 10.0% ตรงกับสัดส่วนของบทที่ 8 「エラーと例外」(ข้อผิดพลาดและข้อยกเว้น) และบทที่ 10 「標準ライブラリめぐり」(ทัวร์ไลบรารีมาตรฐาน) ซึ่งมีบทละ 4 ข้อ การจัดสรรนี้ไม่ใช่ตัวเลขจากการดำเนินงาน แต่เปิดเผยไว้เป็นขอบเขตการสอบเอง จึงใช้เป็นหลักฐานประกอบการวางแผนเรียนได้

ข้อ 4 | การจัดสรรบทที่ 13

ในขอบเขตการสอบวัดพื้นฐาน จำนวนข้อสอบที่จัดสรรให้บทที่ 13 「次はなに?」(ต่อไปคืออะไร?) คือเท่าใด

  1. 0 ข้อ
  2. 1 ข้อ
  3. 4 ข้อ
  4. 2 ข้อ
คำตอบA. 0 ข้อ

บทที่ 13 「次はなに?」(ต่อไปคืออะไร?) มี 0 ข้อ เป็นบทเดียวในขอบเขตการสอบที่ไม่ออกข้อสอบเลย เนื่องจากเป็นเนื้อหาที่แนะนำก้าวต่อไปของการเรียนรู้ จึงถูกตัดออกจากขอบเขตสำหรับการสอบที่ถามเรื่องไวยากรณ์ บทที่ได้รับการจัดสรร 1 ข้อคือบทที่ 1, 2, 7, 11, 12, 14 บทที่ได้ 2 ข้อคือบทที่ 6 และ 9 ส่วนบทที่ได้ 4 ข้อคือบทที่ 8 「エラーと例外」(ข้อผิดพลาดและข้อยกเว้น) และบทที่ 10 「標準ライブラリめぐり」(ทัวร์ไลบรารีมาตรฐาน) นอกจากบทที่ 13 แล้วทุกบทมีอย่างน้อย 1 ข้อ จึงควรเตรียมตัวในระดับที่ผ่านตาศัพท์เฉพาะไว้บ้างแม้ในบทที่มีการจัดสรรน้อย

ข้อ 5 | sep ของ print

เมื่อรันโปรแกรมต่อไปนี้ ข้อความที่แสดงบนหน้าจอคือข้อใด

print('Python', 3, 'exam', sep='/')
  1. Python3exam
  2. Python 3 exam
  3. Python/3/exam/
  4. Python/3/exam
คำตอบD. Python/3/exam

print() จะเชื่อมอาร์กิวเมนต์ที่ได้รับด้วยคีย์เวิร์ดอาร์กิวเมนต์ sep แล้วเรียงต่อกัน ค่าเริ่มต้นของ sep คือช่องว่างครึ่งความกว้าง 1 ตัว หากไม่ระบุจะได้ Python 3 exam แต่ในที่นี้ระบุ sep='/' ไว้ จึงเชื่อมด้วยเครื่องหมายทับกลายเป็น Python/3/exam ส่วน Python3exam เป็นผลลัพธ์เมื่อกำหนดให้ sep เป็นสตริงว่าง การเลือก Python/3/exam/ ที่มีตัวคั่นต่อท้ายด้วยเป็นการคิดว่า sep จะถูกใส่หลังแต่ละองค์ประกอบ แต่ในความเป็นจริง sep จะถูกใส่เฉพาะระหว่างอาร์กิวเมนต์แต่ละตัวเท่านั้น ส่วนที่ใส่ต่อท้ายคือ end

ข้อ 6 | end ของ print

เมื่อรัน 3 บรรทัดต่อไปนี้ตามลำดับจากบนลงล่าง สิ่งที่ปรากฏบนหน้าจอคือข้อใด

print('A', end='')print('B', end='')print('C')
  1. แสดง AB และ C ออกมา 2 บรรทัด
  2. แสดง ABC ออกมาเพียง 1 บรรทัด
  3. แสดง A B C ออกมาเพียง 1 บรรทัด
  4. แสดง A, B, C ออกมา 3 บรรทัด
คำตอบB. แสดง ABC ออกมาเพียง 1 บรรทัด

print() จะใส่คีย์เวิร์ดอาร์กิวเมนต์ end ต่อท้ายเอาต์พุต ค่าเริ่มต้นคืออักขระขึ้นบรรทัดใหม่ หากไม่ระบุจะขึ้นบรรทัดใหม่ทุกครั้งที่เรียก print() ในที่นี้กำหนด end='' ให้กับ 2 บรรทัดแรกเพื่อหยุดการขึ้นบรรทัดใหม่ จึงแสดง A และ B ต่อกัน แล้ว print() บรรทัดสุดท้ายใส่การขึ้นบรรทัดใหม่ตามค่าเริ่มต้น ทำให้แสดง ABC ออกมาเพียง 1 บรรทัด กรณีที่มีช่องว่างคั่นแบบ A B C คือกรณีที่ส่ง 3 อาร์กิวเมนต์ให้ print() เพียงครั้งเดียว กรณีที่แยกเป็น 3 บรรทัดคือกรณีที่ไม่ได้ระบุ end เลย ส่วนกรณีที่เป็น 2 บรรทัดคือกรณีที่ถอด end='' ออกเพียง 1 จุด

ข้อ 7 | เอาต์พุตแบบแกะแพ็ก

โปรแกรมต่อไปนี้แสดงลิสต์แบบแกะออกมา ผลลัพธ์ที่ได้คือข้อใด

nums = [10, 20, 30]print(*nums, sep=', ')
  1. แสดงผล 10, 20, 30
  2. แสดงผล 102030
  3. แสดงผล [10, 20, 30]
  4. แสดงผล 10 20 30
คำตอบA. แสดงผล 10, 20, 30

print(*nums) ที่ใส่เครื่องหมายดอกจันไว้ จะส่งแต่ละองค์ประกอบของลิสต์เป็นอาร์กิวเมนต์แยกกันให้กับ print() ดังนั้น 3 อาร์กิวเมนต์จะถูกเชื่อมด้วย sep และเนื่องจาก sep=', ' จึงได้ 10, 20, 30 หากเขียน print(nums) โดยไม่ใส่ดอกจัน ลิสต์จะถูกส่งเป็นอาร์กิวเมนต์เดียว จึงได้ [10, 20, 30] ที่มีวงเล็บเหลี่ยมติดมาด้วยตามเดิม หากไม่ระบุ sep จะได้ช่องว่างครึ่งความกว้างตามค่าเริ่มต้นกลายเป็น 10 20 30 และหาก sep='' ก็จะติดกันเป็น 102030

ข้อ 8 | สัญลักษณ์คอมเมนต์

ข้อใดคือคำอธิบายที่ถูกต้องเกี่ยวกับคอมเมนต์ของ Python

  1. ช่วงที่ล้อมด้วย /* และ */ จะถูกละเว้นในฐานะคอมเมนต์
  2. ตั้งแต่ # จนถึงท้ายบรรทัดจะถูกละเว้นในฐานะคอมเมนต์
  3. ตั้งแต่ -- จนถึงท้ายบรรทัดจะถูกละเว้นในฐานะคอมเมนต์
  4. ตั้งแต่ // จนถึงท้ายบรรทัดจะถูกละเว้นในฐานะคอมเมนต์
คำตอบB. ตั้งแต่ # จนถึงท้ายบรรทัดจะถูกละเว้นในฐานะคอมเมนต์

คอมเมนต์ของ Python เขียนด้วยเครื่องหมาย # และจะถูกละเว้นตั้งแต่จุดนั้นจนถึงท้ายบรรทัด หากวางไว้ต้นบรรทัดจะครอบคลุมทั้งบรรทัด หากวางไว้กลางบรรทัดจะครอบคลุมตั้งแต่จุดนั้นเป็นต้นไป ไม่มีไวยากรณ์เฉพาะสำหรับรวมหลายบรรทัด จึงต้องใส่ # ทีละบรรทัด การเขียนล้อมด้วยเครื่องหมายคำพูดสามตัวบางครั้งใช้แทนคอมเมนต์แบบบล็อก แต่ในทางไวยากรณ์นั่นคือ string literal ซึ่งหากวางไว้ต้นฟังก์ชันหรือคลาสจะถูกเก็บไว้เป็น docstring เมื่อรัน เครื่องหมายทับสองตัวใน Python เป็นตัวดำเนินการหารปัดเศษลง ส่วน /* */ หรือ -- เป็นรูปแบบคอมเมนต์ของภาษาอื่น

ข้อ 9 | การเว้นวรรค

เมื่อบันทึกโปรแกรมต่อไปนี้ลงไฟล์แล้วรัน จะเกิดอะไรขึ้น

if True:    print('one')        print('two')
  1. แสดงเฉพาะ two แล้วจบการทำงาน
  2. แสดงเฉพาะ one แล้วจบการทำงาน
  3. แสดง one และ two ตามลำดับนี้
  4. เกิด IndentationError แล้วหยุดทำงาน
คำตอบD. เกิด IndentationError แล้วหยุดทำงาน

Python แสดงบล็อกด้วยความลึกของการเว้นวรรค ดังนั้นคำสั่งที่อยู่ในบล็อกเดียวกันต้องมีความกว้างของการเว้นวรรคเท่ากัน บรรทัดที่ 3 เพียงบรรทัดเดียวลึกกว่า และบรรทัดก่อนหน้าก็ไม่ใช่บรรทัดที่นำบล็อกใหม่ (บรรทัดที่ลงท้ายด้วยโคลอน) จึงเกิด IndentationError: unexpected indent เนื่องจากถูกตรวจพบตั้งแต่ขั้นตอนวิเคราะห์ไวยากรณ์ก่อนรันจริง print ในบรรทัดที่ 2 จึงไม่ถูกรันเช่นกัน แม้แต่ one ก็ไม่ถูกแสดง หากไม่เว้นวรรคในจุดที่จำเป็นต้องเว้นจะได้ expected an indented block และหากความกว้างไม่ตรงกันระหว่างทางจะได้ unindent does not match any outer indentation level ซึ่งเป็นข้อความต่างกัน แต่ทั้งหมดล้วนเป็น IndentationError

ข้อ 10 | รหัสอักขระ

ข้อใดอธิบายการเข้ารหัสอักขระของไฟล์ต้นฉบับ Python 3 ได้อย่างถูกต้อง

  1. Shift_JIS เป็นค่าเริ่มต้น สามารถเปลี่ยนได้หากประกาศ
  2. UTF-8 เป็นค่าเริ่มต้น สามารถเขียนภาษาญี่ปุ่นได้โดยตรง
  3. EUC-JP เป็นค่าเริ่มต้น สามารถเขียนภาษาญี่ปุ่นได้โดยตรง
  4. ASCII เป็นค่าเริ่มต้น การใส่ภาษาญี่ปุ่นต้องมีการประกาศ
คำตอบB. UTF-8 เป็นค่าเริ่มต้น สามารถเขียนภาษาญี่ปุ่นได้โดยตรง

ไฟล์ต้นฉบับของ Python 3 ถูกอ่านเป็น UTF-8 โดยค่าเริ่มต้น จึงสามารถเขียนภาษาญี่ปุ่นได้โดยตรงทั้งในคอมเมนต์และ string literal ใน Python 2 ค่าเริ่มต้นคือ ASCII หากต้องการใส่ภาษาญี่ปุ่นจำเป็นต้องเขียนการประกาศ coding ไว้ที่บรรทัดที่ 1 หรือ 2 ของไฟล์ แต่ใน Python 3 ไม่จำเป็นต้องมีการประกาศนี้แล้ว การเขียนประกาศจะจำเป็นเฉพาะเมื่อต้องการให้อ่านไฟล์ที่บันทึกด้วยรหัสอักขระอื่นที่ไม่ใช่ UTF-8 เท่านั้น นอกจากนี้ สามารถใช้ภาษาญี่ปุ่นในตัวระบุ (ชื่อตัวแปรหรือฟังก์ชัน) ได้เช่นกัน แต่ไม่แนะนำในแง่ของการอ่านง่าย

ข้อ 11 | ชนิดของการหาร

โปรแกรมต่อไปนี้จัดการการหารระหว่างจำนวนเต็ม จะแสดงค่าในบรรทัดที่ 1 และชื่อชนิดในบรรทัดที่ 2 ชุดค่าผสมใดถูกต้อง

print(9 / 3)print(type(9 / 3).__name__)
  1. ค่าเป็น 3.0 และชนิดเป็น int
  2. ค่าเป็น 3.0 และชนิดเป็น float
  3. ค่าเป็น 3 และชนิดเป็น int
  4. ค่าเป็น 3 และชนิดเป็น float
คำตอบB. ค่าเป็น 3.0 และชนิดเป็น float

เครื่องหมายทับตัวเดียว / คือการหารจริง ผลลัพธ์จะเป็น float เสมอ แม้ในกรณีที่หารลงตัวก็ไม่มีข้อยกเว้น ดังนั้น 9 / 3 จึงเป็น 3.0 ไม่ใช่ 3 และชนิดก็เป็น float หากคิดว่าเป็นการคำนวณระหว่างจำนวนเต็มจึงต้องเป็น int จะเลือก 3 กับ int ผิด หากต้องการ int ต้องใช้การหารปัดเศษลงเขียนเป็น 9 // 3 ซึ่งจะได้ 3 กับ int ชุดค่าผสมที่ค่ากับชนิดไม่ตรงกัน เช่น 3 กับ float หรือ 3.0 กับ int จะไม่เกิดขึ้นจากนิพจน์นี้

ข้อ 12 | การหารปัดเศษลงของจำนวนลบ

โปรแกรมต่อไปนี้เรียงการหารปัดเศษลงไว้ ผลลัพธ์คือข้อใด

print(9 // 4)print(-9 // 4)
  1. บรรทัดที่ 1 เป็น 2.0 บรรทัดที่ 2 เป็น -3.0
  2. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น -3
  3. บรรทัดที่ 1 เป็น 2.25 บรรทัดที่ 2 เป็น -2.25
  4. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น -2
คำตอบB. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น -3

เครื่องหมายทับสองตัว // คือการหารปัดเศษลง ปัดผลหารลงไปในทิศทางลบ กล่าวคือไปทางค่าที่น้อยกว่าบนเส้นจำนวน 9 / 4 เป็น 2.25 ดังนั้น 9 // 4 จึงเป็น 2 ส่วน -9 / 4 เป็น -2.25 ดังนั้น -9 // 4 จึงเป็น -3 ไม่ใช่ -2 จุดสำคัญคือไม่ใช่ทิศทางเข้าใกล้ 0 การเลือก -2 เป็นการคิดแบบปัดเศษเข้าใกล้ 0 เหมือนภาษา C ส่วน 2.25 และ -2.25 เป็นค่าเมื่อใช้ / แทน // และ 2.0 กับ -3.0 เป็นค่าเมื่อผสม float เข้ากับตัวถูกดำเนินการโดยเขียนเป็น 9.0 // 4 หากทั้งสองข้างเป็น int ผลลัพธ์ก็จะเป็น int เช่นกัน

ข้อ 13 | divmod

divmod(-11, 3) คืนค่าใด

  1. (-4, 1)
  2. (-3, -2)
  3. (-4, -2)
  4. (-3, 2)
คำตอบA. (-4, 1)

divmod(a, b) จะคืนค่าทูเพิล (a // b, a % b) เนื่องจาก // ของ Python ปัดเศษลงในทิศทางลบ -11 // 3 จึงเป็น -4 และเครื่องหมายของเศษจะปรับตามด้านขวา ดังนั้น -11 % 3 จึงเป็น 1 จึงได้ (-4, 1) หากคิดตามวิธีปัดเศษเข้าใกล้ 0 จะได้ผลหาร -3 เศษ -2 กลายเป็น (-3, -2) ซึ่งผิด เพราะ Python ไม่ใช้วิธีนี้ ผลหารและเศษจะรักษาความสัมพันธ์ที่ว่า ตัวหาร คูณ ผลหาร บวก เศษ ต้องเท่ากับค่าตั้งต้นเสมอ ดังนั้น 3 คูณ -4 บวก 1 จะได้ -11 ตรวจสอบได้ หากตรวจสอบด้วยความสัมพันธ์นี้ ทั้ง (-3, 2) และ (-4, -2) ก็ไม่กลับไปเป็น -11

ข้อ 14 | การปัดทิ้งของ int

โปรแกรมต่อไปนี้เปรียบเทียบทิศทางการปัดทิ้ง ผลลัพธ์คือข้อใด

print(int(-2.7))print(-2.7 // 1)
  1. บรรทัดที่ 1 เป็น -2 บรรทัดที่ 2 เป็น -2.0
  2. บรรทัดที่ 1 เป็น -3 บรรทัดที่ 2 เป็น -3.0
  3. บรรทัดที่ 1 เป็น -2 บรรทัดที่ 2 เป็น -3.0
  4. บรรทัดที่ 1 เป็น -3 บรรทัดที่ 2 เป็น -2.0
คำตอบC. บรรทัดที่ 1 เป็น -2 บรรทัดที่ 2 เป็น -3.0

ฟังก์ชันในตัว int() จะตัดส่วนทศนิยมทิ้งและปัดเข้าใกล้ 0 ดังนั้น int(-2.7) จึงเป็น -2 ไม่ใช่ -3 ในขณะที่ // ปัดเศษลงในทิศทางลบ ดังนั้น -2.7 // 1 จึงไปทางฝั่ง -3 และเนื่องจากตัวถูกดำเนินการมี float ผลลัพธ์จึงเป็น float คือ -3.0 สำหรับจำนวนบวก ทั้ง int(2.7) และ 2.7 // 1 ต่างก็ไปทางฝั่ง 2 เหมือนกันจึงมองไม่เห็นความแตกต่าง แต่สำหรับจำนวนลบทิศทางจะแยกออกจากกัน ทั้งสองไม่ใช่การปัดเศษแบบทั่วไป หากต้องการปัด -2.7 เป็น -3 ให้ใช้ round(-2.7)

ข้อ 15 | ความคลาดเคลื่อนของทศนิยม

โปรแกรมต่อไปนี้แสดงค่าความจริงเทียม-เท็จ 2 บรรทัด ผลลัพธ์คือข้อใด

print(0.1 + 0.7 == 0.8)print(round(0.1 + 0.7, 2) == 0.8)
  1. บรรทัดที่ 1 เป็น False บรรทัดที่ 2 เป็น False
  2. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น True
  3. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น False
  4. บรรทัดที่ 1 เป็น False บรรทัดที่ 2 เป็น True
คำตอบD. บรรทัดที่ 1 เป็น False บรรทัดที่ 2 เป็น True

float เก็บทศนิยมในรูปแบบฐาน 2 จึงไม่สามารถแทนค่า 0.1 หรือ 0.7 ที่กระชับในฐาน 10 ได้อย่างแม่นยำ เมื่อลองแสดง 0.1 + 0.7 จริง ๆ จะได้ 0.7999999999999999 ซึ่งต่างจาก 0.8 เล็กน้อย บรรทัดที่ 1 จึงเป็น False บรรทัดที่ 2 เปรียบเทียบหลังปัดเศษด้วย round() ให้เหลือทศนิยม 2 ตำแหน่ง ทั้งสองข้างจึงกลายเป็น 0.8 เท่ากัน ได้ True นี่ไม่ใช่ข้อบกพร่องเฉพาะของ Python แต่เป็นคุณสมบัติของจุดทศนิยมฐาน 2 ตาม IEEE 754 ซึ่งเป็นเหตุผลเดียวกับที่ 0.1 + 0.2 กลายเป็น 0.30000000000000004 และ 1.1 + 2.2 กลายเป็น 3.3000000000000003 ควรหลีกเลี่ยงการเปรียบเทียบความเท่ากันของ float โดยตรง แล้วปัดเศษตามตำแหน่งที่จำเป็นก่อนเปรียบเทียบ หรือเปรียบเทียบค่าสัมบูรณ์ของผลต่างกับค่าความคลาดเคลื่อนที่ยอมรับได้ หรือในกรณีที่ต้องการความแม่นยำอย่างจำนวนเงินให้ใช้โมดูล decimal

ข้อ 16 | การปัดเศษของ round

โปรแกรมต่อไปนี้เรียงค่าที่ปัดเศษแล้วไว้ในบรรทัดเดียว ผลลัพธ์คือข้อใด

print(round(1.5), round(2.5), round(3.5))
  1. 2 2 4
  2. 2 3 4
  3. 1 3 3
  4. 1 2 3
คำตอบA. 2 2 4

round() ของ Python ใช้การปัดเศษแบบเข้าใกล้เลขคู่ที่ใกล้ที่สุด หรือที่เรียกว่าการปัดแบบนายธนาคาร เฉพาะเมื่อค่าอยู่กึ่งกลางพอดีเท่านั้นที่จะปัดไปทางเลขคู่ที่ใกล้กว่า ดังนั้น 1.5 จึงเป็น 2, 2.5 เป็น 2, 3.5 เป็น 4 ผลลัพธ์จึงเป็น 2 2 4 หากปัดเศษแบบที่เรียนในโรงเรียนจะได้ 2 3 4 แต่ Python ไม่ใช้วิธีนี้ 1 2 3 คือค่าเมื่อตัดทศนิยมทิ้งอย่างง่าย ส่วน 1 3 3 คือค่าเมื่อปัดไปทางเลขคี่ ทั้งสองแบบต่างจากพฤติกรรมจริง นอกจากนี้ round() ที่ละอาร์กิวเมนต์ตัวที่ 2 จะคืนค่าเป็น int แต่หากระบุจำนวนหลักอย่าง round(2.5, 0) จะคืนค่า float 2.0

ข้อ 17 | bool คือ int

โปรแกรมต่อไปนี้จัดการค่าความจริงเทียม-เท็จเป็นตัวเลข ผลลัพธ์คือข้อใด

print(True + True)print(isinstance(True, int))
  1. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น True
  2. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น False
  3. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น True
  4. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น False
คำตอบC. บรรทัดที่ 1 เป็น 2 บรรทัดที่ 2 เป็น True

bool เป็นชนิดที่สืบทอดมาจาก int ดังนั้น True คือจำนวนเต็ม 1 และ False คือจำนวนเต็ม 0 สามารถใช้ในการคำนวณเชิงตัวเลขได้โดยตรง True + True คือ 1 บวก 1 จึงเป็น 2 และ isinstance(True, int) จะคืนค่า True การคิดว่าบรรทัดที่ 1 เป็น True คือการเข้าใจผิดว่า + เป็นตรรกะ “หรือ” แต่ตรรกะ “หรือ” ของ Python คือ or ซึ่ง True or True จะได้ True issubclass(bool, int) ก็เป็น True เช่นกัน และ sum([True, False, True]) ก็เป็น 2 ด้วยเหตุผลเดียวกัน คุณสมบัตินี้มักถูกใช้ในการนับจำนวนที่ตรงตามเงื่อนไข

ข้อ 18 | ความแม่นยำของจำนวนเต็ม

ข้อใดคือคำอธิบายที่ถูกต้องเกี่ยวกับชนิด int ของ Python 3

  1. ไม่มีขีดจำกัดของจำนวนหลัก จัดการค่าที่ใหญ่ได้เท่าที่หน่วยความจำอนุญาต
  2. ค่าที่เกิน 32 บิตอาจล้นและกลายเป็นค่าติดลบได้
  3. เมื่อจำนวนหลักเกินขีดจำกัดจะเกิด OverflowError
  4. เมื่อเกิน 64 บิตจะถูกแปลงเป็น float โดยอัตโนมัติแล้วคำนวณ
คำตอบA. ไม่มีขีดจำกัดของจำนวนหลัก จัดการค่าที่ใหญ่ได้เท่าที่หน่วยความจำอนุญาต

int ของ Python 3 มีความแม่นยำตามอำเภอใจ (Arbitrary Precision) ไม่มีขีดจำกัดของจำนวนหลัก 3 ** 40 จะได้ค่าที่แม่นยำคือ 12157665459056928801 ซึ่งเกินขอบเขตของจำนวนเต็ม 64 บิตแบบมีเครื่องหมาย แต่ชนิดยังคงเป็น int ตามเดิม ค่าอย่าง 2 ** 1000 ก็จัดการได้ หากนับจำนวนหลักด้วย len(str(2 ** 1000)) จะได้ 302 หลัก เนื่องจากไม่ใช่จำนวนเต็มความยาวคงที่แบบภาษา C จึงไม่ล้นกลายเป็นค่าติดลบ และไม่เปลี่ยนไปเป็น float เอง OverflowError จะเกิดขึ้นเมื่อเกินขอบเขตที่ float แสดงได้เป็นต้น ไม่ได้เกิดขึ้นเพียงเพราะจำนวนหลักของ int เพิ่มขึ้น แต่ยิ่งจำนวนหลักเพิ่มขึ้น เวลาในการคำนวณและหน่วยความจำก็จะเพิ่มขึ้นตาม

ข้อ 19 | ดัชนีของ bytes

โปรแกรมต่อไปนี้จัดการลำดับไบต์ ผลลัพธ์ในบรรทัดที่ 2 และบรรทัดที่ 3 คือข้อใด

b = 'abc'.encode()print(b[0])print(b[0:1])
  1. บรรทัดที่ 1 เป็น b'a' บรรทัดที่ 2 เป็น b'a'
  2. บรรทัดที่ 1 เป็น 97 บรรทัดที่ 2 เป็น b'a'
  3. บรรทัดที่ 1 เป็น 97 บรรทัดที่ 2 เป็น 97
  4. บรรทัดที่ 1 เป็น a บรรทัดที่ 2 เป็น b'a'
คำตอบB. บรรทัดที่ 1 เป็น 97 บรรทัดที่ 2 เป็น b'a'

การเข้าถึง bytes ด้วยดัชนีที่เป็นจำนวนเต็มจะคืนค่าไบต์ในตำแหน่งนั้นเป็น int ไบต์แรกของ b'abc' ที่เข้ารหัส 'abc' ด้วย UTF-8 คือโค้ดพอยต์ของ 'a' จึงเป็น 97 ในขณะที่การดึงออกมาด้วยการแบ่งส่วน (slice) จะคืนค่าเป็น bytes ที่มีความยาว 1 ดังนั้น b[0:1] จึงเป็น b'a' หากเป็น str แล้ว s[0] และ s[0:1] จะได้ str เดียวกันคือ 'a' นี่คือจุดที่ str กับ bytes ต่างกันอย่างชัดเจน การแสดงผลเป็น b'a' แทนที่จะเป็น a เกิดจาก print() แสดง bytes ในรูปแบบ repr หากต้องการแปลงกลับเป็นสตริงต้องใช้ b.decode()

ข้อ 20 | ฐานเลขและตัวอักษร

โปรแกรมต่อไปนี้เรียงการแปลงฐานเลขและการแปลงรหัสอักขระไว้ ผลลัพธ์คือข้อใด

print(int('1010', 2), bin(10), hex(255), ord('A'))
  1. 10 0b1010 0xff 65
  2. 10 0b1010 0xFF 65
  3. 10 0b1010 0xff 97
  4. 1010 0b1010 0xff 65
คำตอบA. 10 0b1010 0xff 65

อาร์กิวเมนต์ตัวที่ 2 ของ int() คือฐานเลข ดังนั้น int('1010', 2) จะอ่านสตริงเป็นเลขฐาน 2 แล้วคืนค่า 10 การคิดว่าจะได้ 1010 เหมือนเดิมคือการมองข้ามการระบุฐานเลข bin() จะคืนสตริงที่มีคำนำหน้า 0b จึงได้ '0b1010' ส่วน hex() จะคืนสตริงตัวพิมพ์เล็กที่มีคำนำหน้า 0x จึงได้ '0xff' จะไม่กลายเป็น 0xFF ตัวพิมพ์ใหญ่ หากต้องการรูปแบบตัวพิมพ์ใหญ่ให้ใช้ format(255, 'X') ord() จะคืนโค้ดพอยต์ของอักขระ ตัวพิมพ์ใหญ่ A คือ 65 ส่วน 97 คือโค้ดพอยต์ของตัวพิมพ์เล็ก a การแปลงย้อนกลับเขียนเป็น chr(65) จะได้ 'A'

ข้อ 21 | การแบ่งส่วน

โปรแกรมต่อไปนี้จัดการการแบ่งส่วน (slice) ของสตริง ผลลัพธ์คือข้อใด

s = 'Pythonic'print(s[2:5])print(s[-3:])
  1. บรรทัดที่ 1 เป็น tho บรรทัดที่ 2 เป็น nic
  2. บรรทัดที่ 1 เป็น tho บรรทัดที่ 2 เป็น ic
  3. บรรทัดที่ 1 เป็น thon บรรทัดที่ 2 เป็น nic
  4. บรรทัดที่ 1 เป็น yth บรรทัดที่ 2 เป็น nic
คำตอบA. บรรทัดที่ 1 เป็น tho บรรทัดที่ 2 เป็น nic

s[2:5] จะเริ่มจากตำแหน่งดัชนี 2 และดึงมาจนถึงก่อนตำแหน่งดัชนี 5 ดัชนี 2 ของ 'Pythonic' คือ t ดังนั้นจะได้ t, h, o รวม 3 ตัวอักษรคือ tho เนื่องจากไม่รวมตำแหน่งปลายทาง จึงไม่ได้เป็น thon หากอ่านดัชนีโดยเริ่มนับจาก 1 ว่า “ตั้งแต่ตัวที่ 2” จะเลือก yth ซึ่งตรงกับ s[1:4] ผิดไป ส่วน s[-3:] เป็นดัชนีติดลบ จึงนับจากท้าย โดยเริ่มจากตัวอักษรที่ 3 จากท้ายไปจนถึงตัวสุดท้าย จึงได้ nic หากอ่าน -3 ผิดว่า “จนถึงตัวที่ 3 จากท้าย” จะเลือก ic ซึ่งตรงกับ s[-2:] ผิดไป หากจำไว้ 2 จุดคือดัชนีเริ่มจาก 0 และดัชนีติดลบนับจากท้ายโดยให้ท้ายสุดคือ -1 ก็จะไม่สับสน

ข้อ 22 | นอกขอบเขตและ in

โปรแกรมต่อไปนี้แสดงผลการตัดสิน 2 อย่าง ผลลัพธ์คือข้อใด

s = 'Python'print(s[100:200] == '')print('py' in s)
  1. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น False
  2. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น True
  3. บรรทัดที่ 1 เป็น False บรรทัดที่ 2 เป็น True
  4. บรรทัดที่ 1 เป็น False บรรทัดที่ 2 เป็น False
คำตอบA. บรรทัดที่ 1 เป็น True บรรทัดที่ 2 เป็น False

การแบ่งส่วน (slice) จะไม่เกิดข้อยกเว้นแม้ขอบเขตจะเกินความยาวของสตริง จะคืนเฉพาะส่วนที่ทับซ้อนกันเท่านั้น 'Python' มีเพียง 6 ตัวอักษร ดังนั้น s[100:200] จึงเป็นสตริงว่าง การเปรียบเทียบกับสตริงว่างจะได้ True หากเป็นดัชนีเดี่ยว s[100] จะเกิด IndexError ซึ่งเป็นจุดที่ตรงข้ามกัน ตัวดำเนินการ in ในบรรทัดที่ 2 ตรวจสอบว่ามีสตริงย่อยอยู่หรือไม่ แต่จะแยกความแตกต่างระหว่างตัวพิมพ์ใหญ่และเล็ก ดังนั้น 'py' ตัวพิมพ์เล็กจึงไม่มีอยู่ใน 'Python' และได้ False หากเป็น 'Py' หรือ 'th' จะได้ True

ข้อ 23 | สตริงไม่สามารถเปลี่ยนแปลงได้

เมื่อเขียนโปรแกรมต่อไปนี้ลงไฟล์แล้วรัน จะเกิดอะไรขึ้น

s = 'abc's[0] = 'z'print(s)
  1. เกิด TypeError ไม่สามารถกำหนดค่าได้
  2. แสดงผลเป็น zbc ที่ถูกแทนที่แล้ว
  3. เกิด IndexError ไม่สามารถกำหนดค่าได้
  4. แสดงผลเป็น abc โดยไม่เปลี่ยนแปลง
คำตอบA. เกิด TypeError ไม่สามารถกำหนดค่าได้

str เป็นชนิดที่ไม่สามารถเปลี่ยนแปลงได้ (Immutable) หมายความว่าเปลี่ยนแปลงเนื้อหาหลังสร้างขึ้นแล้วไม่ได้ ดังนั้นจึงไม่สามารถใช้ดัชนีเพื่อเขียนทับตัวอักษรบางส่วนได้ s[0] = 'z' จะเกิด TypeError: 'str' object does not support item assignment และหยุดที่จุดนั้น print จึงไม่ถูกรัน IndexError จะเกิดขึ้นเมื่อดัชนีอยู่นอกขอบเขต แต่ในที่นี้ 0 อยู่ในขอบเขตที่ถูกต้อง จึงเป็นคนละกรณี หากต้องการเปลี่ยนเนื้อหาต้องสร้างสตริงใหม่แล้วต่อกันใหม่ เช่น s = 'z' + s[1:] เนื่องจากลิสต์เป็นชนิดที่เปลี่ยนแปลงได้ (Mutable) จึงสามารถเขียนทับองค์ประกอบด้วยวิธีเขียนแบบเดียวกันได้

ข้อ 24 | ค่าที่เมธอดคืนกลับ

โปรแกรมต่อไปนี้เรียกเมธอดของสตริง ผลลัพธ์คือข้อใด

s = 'exam's.upper()print(s)print(s.replace('e', 'E'))
  1. บรรทัดที่ 1 เป็น EXAM บรรทัดที่ 2 เป็น Exam
  2. บรรทัดที่ 1 เป็น EXAM บรรทัดที่ 2 เป็น EXAM
  3. บรรทัดที่ 1 เป็น exam บรรทัดที่ 2 เป็น exam
  4. บรรทัดที่ 1 เป็น exam บรรทัดที่ 2 เป็น Exam
คำตอบD. บรรทัดที่ 1 เป็น exam บรรทัดที่ 2 เป็น Exam

เมธอดของสตริงจะไม่เขียนทับสตริงต้นฉบับ แต่จะสร้างสตริงใหม่แล้วคืนค่ากลับมา บรรทัดที่ 2 s.upper() จะสร้าง 'EXAM' ขึ้นมา แต่เนื่องจากไม่ได้กำหนดค่าให้กับตัวแปรใด ค่านั้นจะถูกทิ้งไป s จึงยังคงเป็น 'exam' เหมือนเดิม ดังนั้น print(s) จึงแสดง exam บรรทัดที่ 4 แสดงค่าที่คืนกลับของ s.replace('e', 'E') โดยตรง จึงแสดง Exam แต่ก็ไม่ได้เปลี่ยนแปลงตัว s เอง หากต้องการเก็บผลลัพธ์ไว้ต้องกำหนดค่าใหม่อย่าง s = s.upper() ซึ่งตรงข้ามกับเมธอดอย่าง sort() ของลิสต์ที่เรียงลำดับในที่เดิมแล้วคืนค่า None

ข้อ 25 | f-string

โปรแกรมต่อไปนี้กำหนดรูปแบบการแสดงผล ผลลัพธ์คือข้อใด

n = 2.71828print(f'{n:.2f}')print(f'{"ok"!r}')
  1. บรรทัดที่ 1 เป็น 2.71 บรรทัดที่ 2 เป็น 'ok'
  2. บรรทัดที่ 1 เป็น 2.72 บรรทัดที่ 2 เป็น ok
  3. บรรทัดที่ 1 เป็น 2.718 บรรทัดที่ 2 เป็น ok
  4. บรรทัดที่ 1 เป็น 2.72 บรรทัดที่ 2 เป็น 'ok'
คำตอบD. บรรทัดที่ 1 เป็น 2.72 บรรทัดที่ 2 เป็น 'ok'

การกำหนดรูปแบบ :.2f ของ f-string จะปัดเศษให้เหลือทศนิยม 2 ตำแหน่งแล้วแสดงผล ดังนั้น 2.71828 จะกลายเป็น 2.72 เนื่องจากไม่ใช่การตัดทิ้ง จึงไม่ได้เป็น 2.71 ส่วน 2.718 เป็นค่าเมื่อเขียนเป็น :.3f บรรทัดที่ 2 !r คือตัวระบุการแปลง ซึ่งจะแสดงค่าในรูปแบบของ repr() หากใช้กับสตริงจะมีเครื่องหมายคำพูดติดมาด้วย จึงได้ 'ok' หากไม่ใส่ !r จะแสดงเป็น ok เฉย ๆ ไวยากรณ์การกำหนดรูปแบบใช้ร่วมกับ str.format() ได้ ดังนั้นเขียน '{n:.2f}'.format(n=2.71828) ก็จะได้ 2.72 เช่นกัน

ข้อ 26 | split

โปรแกรมต่อไปนี้แบ่งสตริง ผลลัพธ์คือข้อใด

print('a b  c'.split())print('a,b,c'.split(',', 1))
  1. ['a', 'b', 'c'] และ ['a', 'b', 'c']
  2. ['a', 'b', '', 'c'] และ ['a', 'b,c']
  3. ['a', 'b', 'c'] และ ['a', 'b,c']
  4. ['a', 'b', '', 'c'] และ ['a', 'b', 'c']
คำตอบC. ['a', 'b', 'c'] และ ['a', 'b,c']

การเรียก split() โดยไม่มีอาร์กิวเมนต์ จะถือว่าช่องว่างที่ต่อเนื่องกันเป็นตัวคั่นเดียวกัน และไม่สร้างองค์ประกอบว่างขึ้นมา ดังนั้น 'a b c'.split() จึงได้ 3 องค์ประกอบคือ ['a', 'b', 'c'] หากระบุตัวคั่นอย่างชัดเจนเป็น 'a b c'.split(' ') จะตัดทีละช่องว่าง 1 ตัว จึงเหลือสตริงว่างและได้ 4 องค์ประกอบคือ ['a', 'b', '', 'c'] อาร์กิวเมนต์ตัวที่ 2 คือ maxsplit ซึ่งกำหนดขีดจำกัดของจำนวนครั้งในการแบ่ง หากส่งค่า 1 จะตัดเพียงครั้งแรกเท่านั้น จึงได้ ['a', 'b,c'] ส่วนที่เหลือจะไม่ถูกตัดและรวมเป็นองค์ประกอบเดียว หากละไว้จะตัดทั้งหมดกลายเป็น ['a', 'b', 'c']

ข้อ 27 | strip

โปรแกรมต่อไปนี้ตัดตัวอักษรที่ปลายทั้งสองข้างออก ผลลัพธ์คือข้อใด

print('xxabxx'.strip('x'))print('xxabxx'.lstrip('x'))
  1. บรรทัดที่ 1 เป็น abxx บรรทัดที่ 2 เป็น ab
  2. บรรทัดที่ 1 เป็น ab บรรทัดที่ 2 เป็น abxx
  3. บรรทัดที่ 1 เป็น xabx บรรทัดที่ 2 เป็น abxx
  4. บรรทัดที่ 1 เป็น ab บรรทัดที่ 2 เป็น xxab
คำตอบB. บรรทัดที่ 1 เป็น ab บรรทัดที่ 2 เป็น abxx

อาร์กิวเมนต์ของ strip() คือ “ชุดของตัวอักษรที่จะตัดออก” จะตัดตัวอักษรที่อยู่ในชุดนั้นออกจากปลายทั้งสองข้างต่อเนื่องไปเรื่อย ๆ ไม่ใช่การลบสตริงย่อย 'x' เพียง 1 ตัว ดังนั้น 'xxabxx'.strip('x') จะตัด x ที่ปลายทั้งสองข้างออกทั้งหมด เหลือ ab หากคิดว่าจะตัดทีละ 1 ตัวอักษรจะเลือก xabx ผิด lstrip() จะกระทำเฉพาะปลายซ้าย จึงได้ abxx ส่วน rstrip() กระทำเฉพาะปลายขวา จึงได้ xxab หากละอาร์กิวเมนต์จะตัดอักขระช่องว่าง เนื่องจากถูกจัดการเป็นชุด หากเขียน 'xxabxx'.strip('xa') จะตัด xx ที่ปลายซ้ายและ a ออกไปด้วย เหลือเพียง b เท่านั้น

ข้อ 28 | join และการทำซ้ำ

โปรแกรมต่อไปนี้เชื่อมสตริง ผลลัพธ์คือข้อใด

print('-'.join('abc'))print('ab' * 3)
  1. บรรทัดที่ 1 เป็น -a-b-c- บรรทัดที่ 2 เป็น ababab
  2. บรรทัดที่ 1 เป็น abc บรรทัดที่ 2 เป็น ababab
  3. บรรทัดที่ 1 เป็น a-b-c บรรทัดที่ 2 เป็น ab ab ab
  4. บรรทัดที่ 1 เป็น a-b-c บรรทัดที่ 2 เป็น ababab
คำตอบD. บรรทัดที่ 1 เป็น a-b-c บรรทัดที่ 2 เป็น ababab

join() จะใช้สตริงฝั่งที่เรียกเป็นตัวคั่น แล้วเชื่อมแต่ละองค์ประกอบของอ็อบเจกต์ที่วนซ้ำได้ที่ส่งเข้ามา สตริงเองก็เป็นอ็อบเจกต์ที่วนซ้ำได้ทีละตัวอักษร ดังนั้น '-'.join('abc') จะเชื่อม 'a', 'b', 'c' ด้วยเครื่องหมายยัติภังค์ ได้ a-b-c เนื่องจากตัวคั่นจะถูกใส่เฉพาะระหว่างองค์ประกอบเท่านั้น จึงไม่ติดที่ต้นหรือท้าย ไม่ได้เป็น -a-b-c- กรณีที่ไม่มีตัวคั่นแทรกอยู่เลยกลายเป็น abc คือกรณีที่เขียน ''.join('abc') ตัวดำเนินการ * จะทำซ้ำสตริงตามจำนวนครั้งที่ระบุ ดังนั้น 'ab' * 3 จึงได้ ababab โดยไม่มีช่องว่างคั่นระหว่างกลาง หากต้องการ ab ab ab ต้องเขียนเป็น ' '.join(['ab'] * 3)

ข้อ 29 | find และ index

โปรแกรมต่อไปนี้ค้นหาสตริงย่อย ผลลัพธ์คือข้อใด

print('banana'.find('z'))print('banana'.index('n'))
  1. บรรทัดที่ 1 เป็น -1 บรรทัดที่ 2 เป็น 2
  2. บรรทัดที่ 1 เป็น -1 บรรทัดที่ 2 เป็น 3
  3. บรรทัดที่ 1 เป็น -1 บรรทัดที่ 2 เป็น 4
  4. บรรทัดที่ 1 เป็น 0 บรรทัดที่ 2 เป็น 2
คำตอบA. บรรทัดที่ 1 เป็น -1 บรรทัดที่ 2 เป็น 2

find() จะคืนค่า -1 เมื่อไม่พบสตริงย่อย โดยไม่เกิดข้อยกเว้น เนื่องจากไม่มี 'z' อยู่ใน 'banana' จึงเป็น -1 ค่า 0 คือค่าเมื่อพบที่ตำแหน่งเริ่มต้น จึงไม่ควรสับสนกับกรณีไม่พบ index() คืนตำแหน่งที่พบเช่นเดียวกับ find() 'n' ตัวแรกที่ปรากฏใน 'banana' อยู่ที่ดัชนี 2 จึงได้ 2 ค่า 3 คือกรณีนับดัชนีเริ่มจาก 1 แล้วอ่านว่า “ตัวที่ 3” ผิดไป ส่วน 4 คือตำแหน่งที่ปรากฏครั้งสุดท้าย หากต้องการค่านี้ต้องใช้ rfind() หรือ rindex() ความแตกต่างระหว่างทั้งสองมีเฉพาะกรณีไม่พบ ซึ่ง index() จะส่ง ValueError: substring not found และหยุดการทำงาน

ข้อ 30 | raw string

โปรแกรมต่อไปนี้นับจำนวนตัวอักษร ผลลัพธ์คือข้อใด

print(len(r'a\nb'), len('a\nb'))
  1. 3 4
  2. 4 4
  3. 3 3
  4. 4 3
คำตอบD. 4 3

raw string ที่ใส่ r นำหน้า literal จะไม่ตีความแบ็กสแลชเป็นจุดเริ่มต้นของ escape r'a\nb' จึงมี 4 ตัวอักษรคือ a, แบ็กสแลช, n, b ดังนั้น len จึงเป็น 4 ในขณะที่สตริงปกติ 'a\nb' \n จะถูกแทนที่ด้วยอักขระขึ้นบรรทัดใหม่ 1 ตัว จึงมี 3 ตัวอักษรคือ a, ขึ้นบรรทัดใหม่, b ดังนั้น len จึงเป็น 3 หากนับทั้งสองแบบเป็น escape จะได้ 3 3 หากนับทั้งสองแบบเป็นตัวอักษรดิบจะได้ 4 4 แต่จุดสำคัญคือการมีหรือไม่มี r จะทำให้การตีความต่างกัน แม้จะใส่ r ชนิดก็ยังคงเป็น str ปกติ ไม่ได้กลายเป็นชนิดพิเศษ นอกจากนี้ len('\\') คือ 1 เนื่องจากต้องเขียนแบ็กสแลชซ้อนกัน 2 ตัวเพื่อแทนแบ็กสแลช 1 ตัวอักษร

ฝึกทำ: ทำโจทย์ในหน้านี้

เครื่องมือฝึกทำโจทย์แบบสุ่มคำถาม (ทำงานเมื่อเปิดใช้ JavaScript) โจทย์และคำอธิบายด้านบนสามารถอ่านได้ทั้งหมดตามปกติ

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

หน้านี้แปลจากต้นฉบับภาษาญี่ปุ่น หากเนื้อหาของคำแปลและต้นฉบับไม่ตรงกัน ให้ถือฉบับภาษาญี่ปุ่นเป็นหลัก ดูต้นฉบับภาษาญี่ปุ่น