{
  "assessmentTests": {
    "python_test": {
      "name": "Python Test",
      "desc": "30 คำถามสถานการณ์เกี่ยวกับไวยากรณ์ ฟังก์ชัน โครงสร้างข้อมูล และพฤติกรรมของออบเจกต์ — ค้นหาว่า Python ของคุณตรงกับความหมายของ \"ความชำนาญ Python\" ในประกาศรับสมัครหรือไม่",
      "recommendation": "โปรไฟล์ทักษะ Python ของคุณ",
      "results": {
        "beginner": {
          "name": "ผู้เริ่มต้น",
          "desc": "คุณสามารถทำตามสคริปต์สั้นและเปลี่ยนค่าข้างใน แต่คำถามที่คุณตอบผิดส่วนใหญ่กลุ่มอยู่รอบพฤติกรรมเฉพาะของภาษา ไม่ใช่ตรรกะทั่วไป — อาร์กิวเมนต์เริ่มต้นที่สร้างครั้งเดียวและนำกลับมาใช้ใหม่ `is` เทียบกับ `==` ในสองลิสต์ที่ดูเหมือนกัน ตัวแปรที่กลายเป็นโลคัลในขณะที่คุณกำหนดให้ที่ใดก็ตามในฟังก์ชัน นี่ไม่ใช่เรื่องของความไม่ดีในการเขียนโปรแกรม เหล่านี้คือกฎเฉพาะของ Python ที่ทำให้คนที่มาจากภาษาอื่นสับสนเท่าๆ กับผู้เริ่มต้น พวกเขาสำคัญที่งานเพราะแต่ละข้อคือที่ที่บักซ่อนอยู่ในโค้ดที่ดูถูกต้องในมุมมองแรก",
          "recommendation": "เริ่มต้นด้วยสิ่งสามอย่าง ตามลำดับ: อาร์กิวเมนต์เริ่มต้นที่เปลี่ยนแปลงได้ (ทำไม `basket=[]` จึงอันตราย) ความแตกต่างระหว่าง `is` และ `==` และวิธีการที่ขอบเขตตัวแปรทำงานภายในฟังก์ชัน บทช่วยสอนอย่างเป็นทางการของ Python ที่ docs.python.org ครอบคลุมทั้งสามอย่างโดยตรง และคำว่า \"Python gotchas\" ส่งให้ตัวอย่างที่ใช้งานได้ของแต่ละอย่าง"
        },
        "intermediate": {
          "name": "ระดับกลาง",
          "desc": "คุณจัดการการเขียนสคริปต์ในชีวิตประจำวันได้อย่างสะดวก — โครงสร้างข้อมูล โฟลว์ของการควบคุม ฟังก์ชันที่ตรงไปตรงมา — และจะไม่ช้าลงจากงานบำรุงรักษาแบบปกติหรือฟีเจอร์เล็กน้อยบนโค้ดเบส ช่องว่างระหว่างที่นี่กับ Advanced ส่วนใหญ่อยู่ในสิ่งที่เกิดขึ้นเมื่อฟีเจอร์ความสะดวกของ Python โต้ตอบซึ่งกันและกัน: สำเนาตื้นปล่อยให้ข้อมูลที่ซ้อนกันแบ่งปันเมื่อคุณคาดหวังว่าจะซ้ำเป็นทำนาย ค่าการส่งคืนของตัวสร้างอย่างเงียบ ๆ ไม่กลายเป็นส่วนของผลลัพธ์ของมัน ตัวแปรเดกอเรเตอร์ซ้อนกันในลำดับที่ง่ายต่อการได้รับแบบย้อนกลับ สิ่งเหล่านี้คือประเภทของบักที่ผู้ตรวจสอบสูงอายุทำเครื่องหมายในสิบวินาที และคนอื่น ๆ ใช้เวลาหนึ่งชั่วโมงไล่ตามหา",
          "recommendation": "เน้นไปที่ออบเจกต์และภายในของการวนซ้ำ: สำเนาตื้นเทียบกับสำเนาลึก สิ่งที่ตัวสร้างทำจริง ๆ กับการส่งคืน และวิธีการที่ลำดับการซ้อนตัวแปรเดกอเรเตอร์ทำงาน จากนั้นพื้นฐานของคลาสที่บทช่วยสอนส่วนใหญ่ข้าม — ความเท่าเทียมกันโดยค่าเริ่มต้นโดยไม่มี `__eq__` และทำไมแอตทริบิวต์คลาสที่เปลี่ยนแปลงได้จึงถูกแบ่งปันในทุกอินสแตนซ์"
        },
        "advanced": {
          "name": "ขั้นสูง",
          "desc": "นี่คือระดับที่ประกาศรับสมัครส่วนใหญ่หมายถึง \"Python ที่แข็งแกร่ง\" คุณยื่นไปยังเครื่องมือที่ถูกต้องโดยไม่ต้องหาหา คุณรู้ว่าทำไมสถานะที่ใช้ร่วมกันจึงเปลี่ยนแปลงแทนที่จะเพียงแค่รู้ว่ามันเปลี่ยนแปลง และคุณสามารถอ่านฟังก์ชันของคนอื่นและทำนายผลลัพธ์ของมันได้อย่างถูกต้อง สิ่งที่แยกแยะแถบนี้จากด้านบนคือด้านป้องกันของงาน: รู้ว่าสองวิธีที่ดูถูกต้องจากคู่ใดจะ misbehave เมื่ออแตทริบิวต์คลาส อาร์กิวเมนต์โครงสร้างเฉพาะคำหลัก หรือลำดับชั้นข้อยกเว้นเกี่ยวข้อง",
          "recommendation": "ดันเข้าไปในส่วนที่ปกป้องโค้ดเบส ที่คนอื่น ๆ จะแตะ: อาร์กิวเมนต์โครงสร้างเฉพาะคำหลักเป็นการเลือก API-design แทนที่จะเป็นความอยากรู้อยากเห็นในไวยากรณ์ ลำดับชั้นข้อยกเว้น (เพื่อให้ `except` ประโยค catch ครอบครัวที่เหมาะสมของข้อผิดพลาด ไม่ใช่แค่คลาสเดียว) และตัวจัดการบริบทเป็นวิธีมาตรฐานเพื่อรับประกันการทำความสะอาด บทความเจาะลึกของ Real Python เป็นจุดหยุดต่อไปที่ดีสำหรับทั้งสาม"
        },
        "expert": {
          "name": "ผู้เชี่ยวชาญ",
          "desc": "คุณทำคะแนนที่ด้านบนสุดของทุกส่วน — ไวยากรณ์หลัก ฟังก์ชันและขอบเขต โครงสร้างข้อมูล และนิสัยเชิงวัตถุ ในทางปฏิบัติ นั่นหมายความว่าคุณสามารถมอบไฟล์ของคนแปลกหน้าและอธิบายว่าทำไมมันจึงสร้างผลลัพธ์ที่เป็นผล ไม่ใช่เพียงสิ่งที่ไวยากรณ์บอกว่ามันควรจะทำ ซึ่งเป็นทักษะที่ยากและมีคุณค่ามากขึ้น ในระดับนี้ ภาษาดิบนั้นแทบจะไม่มีปัจจัยจำกัดในงานของคุณ ข้อจำกัดมักจะเป็นขนาดหรือรูปร่างของระบบรอบ ๆ โค้ด",
          "recommendation": "ผลตอบแทนตอนนี้อยู่ในเครื่องมือและการทบทวน: การตรวจสอบประเภทคงที่ด้วย mypy หรือ pyright การโปรไฟล์ก่อนการปรับให้เหมาะสมแทนที่จะเดา และการอ่านคำขอดึงของคนอื่นสำหรับหมวดหมู่ของบักนี้อย่างแม่นยำ — สิ่งที่ผ่านการทดสอบทุกครั้งและยังคงทำสิ่งที่ผิดภายใต้อินพุตที่เฉพาะเจาะจง หากคุณอยู่ภายใต้การคัดกรองสำหรับบทบาท ให้อธิบายบักเช่นนี้แทนที่จะตั้งชื่อลักษณะภาษา — มันแสดงการใช้เหตุผล ไม่ใช่เพียงคำศัพท์"
        }
      },
      "questions": [
        {
          "question": "คุณเขียน `def add_item(item, basket=[]): basket.append(item); return basket` จากนั้นเรียก `add_item('a')` และ `add_item('b')` ทั้งสองครั้งโดยปล่อยให้ basket ออก สิ่งที่ครั้งที่สองเรียกส่งกลับคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`['b']` — การเรียกแต่ละครั้งได้รับรายการเปล่าใหม่โดยค่าเริ่มต้น"
            },
            {
              "icon": "",
              "label": "TypeError — คุณต้องระบุอาร์กิวเมนต์ basket"
            },
            {
              "icon": "",
              "label": "`['a', 'b']` — รายการเริ่มต้นถูกสร้างครั้งเดียวและนำกลับมาใช้ใหม่ในการเรียก"
            },
            {
              "icon": "",
              "label": "`['a']` จากนั้น `['b']` เป็นรายการเดี่ยวที่เป็นอิสระสองรายการ"
            }
          ]
        },
        {
          "question": "`a = [1, 2, 3]` และ `b = [1, 2, 3]` สิ่งที่ `a == b` ส่งคืนคืออะไร และ `a is b` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "True สำหรับทั้งสอง — รายการที่เหมือนกันจะเป็นอบเจกต์เดียวกันเสมอ"
            },
            {
              "icon": "",
              "label": "True สำหรับ `==` False สำหรับ `is` — เนื้อหาเท่ากัน แต่เป็นอบเจกต์ที่แตกต่างกันในหน่วยความจำ"
            },
            {
              "icon": "",
              "label": "False สำหรับทั้งสอง — ลิเทอรัลแยกต่างหากไม่เท่าเทียมกันใน Python"
            },
            {
              "icon": "",
              "label": "True สำหรับ `is` False สำหรับ `==` — `is` ตรวจสอบความเท่าเทียมกันของค่าสำหรับรายการ"
            }
          ]
        },
        {
          "question": "ใน Python 3 `7 / 2` ประเมินค่าเป็นอะไร และ `7 // 2` ประเมินค่าเป็นอะไร",
          "options": [
            {
              "icon": "",
              "label": "3.5 จากนั้น 3 — `/` สร้างคืน float เสมอ `//` ปูพื้นผลลัพธ์"
            },
            {
              "icon": "",
              "label": "3 จากนั้น 3.5 — `/` ตัดตอน และ `//` ส่งคืน float"
            },
            {
              "icon": "",
              "label": "3.5 จากนั้น 3.5 — ตัวดำเนินการทั้งคู่ส่งคืน float ใน Python 3"
            },
            {
              "icon": "",
              "label": "3 จากนั้น 3 — ตัวดำเนินการทั้งคู่ปูพื้นผลลัพธ์ใน Python 3"
            }
          ]
        },
        {
          "question": "`s = 'hello'` จากนั้นคุณเรียก `s[0] = 'H'` จะเกิดอะไรขึ้น",
          "options": [
            {
              "icon": "",
              "label": "s กลายเป็น 'Hello'"
            },
            {
              "icon": "",
              "label": "s กลายเป็น 'Hhello' เพราะถูกแทรกอักขระ ไม่ใช่แทนที่"
            },
            {
              "icon": "",
              "label": "TypeError — สตริงไม่เปลี่ยนแปลงได้และไม่รองรับการกำหนดรายการ"
            },
            {
              "icon": "",
              "label": "ไม่มีอะไร — การกำหนดจะถูกละเว้นโดยเงียบและ s ยังคงเป็น 'hello'"
            }
          ]
        },
        {
          "question": "`x = [10, 20, 30, 40, 50]` สิ่งที่ `x[1:4]` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`[20, 30, 40, 50]`"
            },
            {
              "icon": "",
              "label": "`[10, 20, 30, 40]`"
            },
            {
              "icon": "",
              "label": "`[20, 30, 40]`"
            },
            {
              "icon": "",
              "label": "`[30, 40]`"
            }
          ]
        },
        {
          "question": "`name = 'Ana'` และ `age = 30` สิ่งที่ `f'{name} is {age}'` สร้างคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`{name} is {age}`"
            },
            {
              "icon": "",
              "label": "Ana is 30"
            },
            {
              "icon": "",
              "label": "name is age"
            },
            {
              "icon": "",
              "label": "TypeError เพราะ f-strings ต้องการวิธี `format()`"
            }
          ]
        },
        {
          "question": "`1 < 2 < 3` ประเมินค่าเป็นอะไร",
          "options": [
            {
              "icon": "",
              "label": "True — Python เชื่อมโยงการเปรียบเทียบเป็น `(1 < 2) and (2 < 3)`"
            },
            {
              "icon": "",
              "label": "False — การเปรียบเทียบแบบเชื่อมโยงจะถูกประเมินจากซ้ายไปขวาโดยไม่มีการตัดวงจร ให้ `1 < 2 < 3 -> 1 < True -> False`"
            },
            {
              "icon": "",
              "label": "SyntaxError — ไม่สามารถเชื่อมโยงการเปรียบเทียบได้"
            },
            {
              "icon": "",
              "label": "3 — Python ส่งคืนค่าสุดท้ายในเชน"
            }
          ]
        },
        {
          "question": "`bool([])` ส่งคืนอะไร และ `bool([0])` ส่งคืนอะไร",
          "options": [
            {
              "icon": "",
              "label": "False จากนั้น False — รายการใด ๆ ที่มีเฉพาะค่าที่เป็นเท็จคือเท็จ"
            },
            {
              "icon": "",
              "label": "False จากนั้น True — รายการเปล่าเป็นเท็จ รายการที่มีองค์ประกอบหนึ่ง (แม้แต่ 0) เป็นจริง"
            },
            {
              "icon": "",
              "label": "True จากนั้น True — อบเจกต์ที่ไม่ใช่ None จะเป็นจริงเสมอ"
            },
            {
              "icon": "",
              "label": "True จากนั้น False — รายการเป็นจริงเฉพาะเมื่อว่างเปล่า"
            }
          ]
        },
        {
          "question": "มีโมดูล `count = 0` ระดับ ภายในฟังก์ชัน `def increment(): count += 1; return count` คุณเรียก `increment()` จะเกิดอะไรขึ้น",
          "options": [
            {
              "icon": "",
              "label": "UnboundLocalError — การกำหนดให้ count ที่ใดก็ตามในฟังก์ชันทำให้เป็นโลคัล ดังนั้น `count += 1` พยายามอ่านตัวแปรโลคัลก่อนที่จะถูกกำหนด"
            },
            {
              "icon": "",
              "label": "มันส่งคืน 1 และเพิ่มขึ้น count ระดับโมดูลเป็น 1"
            },
            {
              "icon": "",
              "label": "มันส่งคืน 1 แต่ปล่อยให้ count ระดับโมดูลเป็น 0"
            },
            {
              "icon": "",
              "label": "มันเพิ่ม NameError เพราะ count ไม่เคยถูกประกาศภายในฟังก์ชัน"
            }
          ]
        },
        {
          "question": "`def f(*args, **kwargs): return args, kwargs` สิ่งที่ `f(1, 2, x=3)` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`([1, 2], {'x': 3})`"
            },
            {
              "icon": "",
              "label": "`((1, 2), {'x': 3})`"
            },
            {
              "icon": "",
              "label": "`(1, 2, {'x': 3})`"
            },
            {
              "icon": "",
              "label": "TypeError — ไม่สามารถผสมอาร์กิวเมนต์ตำแหน่งและคำหลักในการเรียกเดียวได้"
            }
          ]
        },
        {
          "question": "คุณสร้าง `funcs = [lambda: i for i in range(3)]` ในลูป สิ่งที่ `[f() for f in funcs]` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`[2, 2, 2]` — lambda แต่ละอันค้นหา i เมื่อเรียก และในขณะนั้นลูปจะสิ้นสุดด้วย i เท่ากับ 2"
            },
            {
              "icon": "",
              "label": "`[0, 1, 2]` — lambda แต่ละอันจับค่า i ตามเวลาที่สร้างขึ้น"
            },
            {
              "icon": "",
              "label": "`[0, 0, 0]` — lambdas จับค่าแรกที่กำหนดให้กับตัวแปรเสมอ"
            },
            {
              "icon": "",
              "label": "NameError เพราะ i ไม่มีอยู่อีกต่อไปเมื่อลูปสิ้นสุด"
            }
          ]
        },
        {
          "question": "ฟังก์ชันถูกกำหนดด้วย `@a` โดยตรงเหนือ `@b` ซึ่งนั่งเหนือ `def f(): pass` ลำดับที่ตัวแปรเดกอเรเตอร์ถูกนำไปใช้กับ f คืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`b` ห่อ f ก่อน จากนั้น `a` ห่อผลลัพธ์ของ `b` — ตัวแปรเดกอเรเตอร์ที่ใกล้กับฟังก์ชันที่สุดจะทำงานก่อน"
            },
            {
              "icon": "",
              "label": "`a` ห่อ f ก่อน จากนั้น `b` ห่อผลลัพธ์ — ตัวแปรเดกอเรเตอร์ใช้จากบนลงล่าง"
            },
            {
              "icon": "",
              "label": "ตัวแปรเดกอเรเตอร์ทั้งสองห่อ f โดยอิสระและมีเพียงตัวแปรเดกอเรเตอร์สุดท้ายที่กำหนดเท่านั้นที่ใช้ได้"
            },
            {
              "icon": "",
              "label": "ขึ้นอยู่กับลำดับการนำเข้าตัวแปรเดกอเรเตอร์ ไม่ใช่ตำแหน่งของพวกเขาในโค้ด"
            }
          ]
        },
        {
          "question": "`def f(a, *, b): return a + b` การเรียกเหล่านี้ใดที่ทำงาน",
          "options": [
            {
              "icon": "",
              "label": "`f(1, b=2)` — `b` ต้องถูกส่งผ่านคำหลักเพราะมาหลัง `*` เปล่าในลายเซน"
            },
            {
              "icon": "",
              "label": "`f(1, 2)` — อาร์กิวเมนต์ตำแหน่งเติมพารามิเตอร์จากซ้ายไปขวาโดยไม่คำนึงถึง `*`"
            },
            {
              "icon": "",
              "label": "`f(a=1, 2)` — อาร์กิวเมนต์คำหลักต้องมาก่อน"
            },
            {
              "icon": "",
              "label": "`f(1)` — `b` เป็นทางเลือกเพราะตามมา `*`"
            }
          ]
        },
        {
          "question": "ฟังก์ชัน generator yields 1 จากนั้น yields 2 จากนั้น `return 99` รายการที่ `list(the_generator())` มีคืออะไร และ 99 จะเกิดอะไรขึ้น",
          "options": [
            {
              "icon": "",
              "label": "`[1, 2, 99]` — return ภายใน generator ทำงานเหมือน yields หนึ่งอันเพิ่มเติม"
            },
            {
              "icon": "",
              "label": "`[99]` — return ลบล้างค่าที่ yield ใด ๆ แล้ว"
            },
            {
              "icon": "",
              "label": "`[1, 2]` — ค่าส่งคืนของ generator กลายเป็นค่าที่แนบมากับ StopIteration ที่มันเพิ่มขึ้น มันไม่ได้ yield"
            },
            {
              "icon": "",
              "label": "RuntimeError เพราะ generators ไม่สามารถมี `return` statement"
            }
          ]
        },
        {
          "question": "ในฟังก์ชัน `outer()` `x = 1` ตั้งไว้ จากนั้น `inner()` ที่ซ้อนกันทำ `nonlocal x; x += 1` และ `outer()` เรียก `inner()` ก่อนส่งคืน x สิ่งที่ `outer()` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "1 — `inner()` ทำงานบนสำเนาโลคัลของ x ดังนั้นการเปลี่ยนแปลงไม่ยังคง"
            },
            {
              "icon": "",
              "label": "UnboundLocalError เพราะ x ไม่ได้ประกาศภายใน `inner()` ก่อน `nonlocal` statement"
            },
            {
              "icon": "",
              "label": "SyntaxError — `nonlocal` ใช้ได้เฉพาะในคลาสเท่านั้น"
            },
            {
              "icon": "",
              "label": "2 — `nonlocal` ให้ `inner()` แก้ไข x ของฟังก์ชันภายนอกแทนที่จะสร้างตัวแปรโลคัลใหม่"
            }
          ]
        },
        {
          "question": "`d = {'a': 1, 'b': 2}` สิ่งที่ `d.get('c', 0)` ส่งคืนคืออะไร และมันเพิ่ม 'c' ลงในพจนานุกรมหรือไม่",
          "options": [
            {
              "icon": "",
              "label": "0 และไม่ — `get()` ส่งคืนค่าเริ่มต้นโดยไม่แทรกคีย์"
            },
            {
              "icon": "",
              "label": "0 และใช่ — `get()` แทรกคีย์ด้วยค่าเริ่มต้น"
            },
            {
              "icon": "",
              "label": "KeyError เพราะ 'c' ไม่มีอยู่"
            },
            {
              "icon": "",
              "label": "None และใช่ — `get()` เพิ่มคีย์ที่หายไปด้วยค่า None เสมอ"
            }
          ]
        },
        {
          "question": "`t = (1, 2, [3, 4])` คุณสามารถเรียก `t[2].append(5)` ได้และคุณสามารถเรียก `t[0] = 10` ได้",
          "options": [
            {
              "icon": "",
              "label": "ทั้งสองทำงาน — การซ้อนรายการภายใน tuple ทำให้ tuple ทั้งหมดเปลี่ยนแปลงได้"
            },
            {
              "icon": "",
              "label": "ทั้งสองเพิ่ม TypeError — ไม่มีอะไรภายใน tuple ที่เปลี่ยนแปลงได้เลย"
            },
            {
              "icon": "",
              "label": "`t[2].append(5)` เพิ่ม TypeError แต่ `t[0] = 10` ทำงานเพราะ tuples อนุญาตการกำหนดใหม่ขององค์ประกอบแรก"
            },
            {
              "icon": "",
              "label": "`t[2].append(5)` ทำงานเพราะรายการภายในเปลี่ยนแปลงได้; `t[0] = 10` เพิ่ม TypeError เพราะ tuple นั้นไม่เปลี่ยนแปลงได้"
            }
          ]
        },
        {
          "question": "ซึ่งของสิ่งเหล่านี้ส่งคืนตัววนซ้ำที่คำนวณค่าอย่างการขี้ลัพอย่างเบาบาง แทนที่จะสร้างลำดับทั้งหมดในหน่วยความจำในครั้งเดียว: `[x*x for x in range(1000000)]` หรือ `(x*x for x in range(1000000))`",
          "options": [
            {
              "icon": "",
              "label": "ที่มีวงเล็บ `(x*x for x in range(1000000))` — นี่คือนิพจน์ generator"
            },
            {
              "icon": "",
              "label": "ที่มีวงเล็บสี่เหลี่ยม — list comprehensions จะเป็นการขี้ลัพอเสมอใน Python 3"
            },
            {
              "icon": "",
              "label": "ทั้งสองเป็นการขี้ลัพอ — ความแตกต่างเพียงอย่างเดียวคือประเภทที่ส่งคืนในตอนท้าย"
            },
            {
              "icon": "",
              "label": "ไม่มีคน — ทั้งสองสร้างลำดับเต็มในหน่วยความจำทันที"
            }
          ]
        },
        {
          "question": "ไตรแบล try ระเบิดตัวแปร except `ZeroDivisionError` ประโยคพิมพ์ 'a' และประโยค `finally` พิมพ์ 'b' พิมพ์อะไร และในลำดับใด",
          "options": [
            {
              "icon": "",
              "label": "b จากนั้น a — `finally` ทำงานเสมอก่อน except ประโยค"
            },
            {
              "icon": "",
              "label": "a จากนั้น b — matching except ทำงานก่อน และ `finally` ทำงานเสมอหลังจากนั้นโดยไม่คำนึงถึง"
            },
            {
              "icon": "",
              "label": "เพียง b — ข้อยกเว้นไม่ได้ถูกจับจริง ๆ ดังนั้น 'a' จึงไม่พิมพ์"
            },
            {
              "icon": "",
              "label": "เพียง a — `finally` ถูกข้ามเมื่อข้อยกเว้นถูกจัดการแล้ว"
            }
          ]
        },
        {
          "question": "`import copy; a = [[1, 2], [3, 4]]; b = copy.copy(a); b[0].append(99)` มี `a[0]` เปลี่ยนแปลงเช่นกัน",
          "options": [
            {
              "icon": "",
              "label": "ไม่ — `copy.copy()` เพิ่มเติมออบเจกต์ที่ซ้อนกันเสมอ"
            },
            {
              "icon": "",
              "label": "ไม่ — การเพิ่มเติมเป็น `b[0]` สร้างรายการใหม่สำหรับ `b[0]` เพียงอย่างเดียว"
            },
            {
              "icon": "",
              "label": "ใช่ แต่เพียงเพราะ `copy.copy()` ถูกเรียกโดยไม่มีอาร์กิวเมนต์ deepcopy"
            },
            {
              "icon": "",
              "label": "ใช่ — `copy.copy()` ทำสำเนาตื้น ดังนั้นรายการที่ซ้อนกันยังคงแบ่งปันระหว่าง a และ b"
            }
          ]
        },
        {
          "question": "`d = {'x': 1, 'y': 2}` สิ่งที่ `'x' in d` ตรวจสอบกับ — คีย์ ค่า หรือทั้งสอง",
          "options": [
            {
              "icon": "",
              "label": "ค่า — `in` ตรวจสอบว่า 1 หรือ 2 เท่ากับ 'x'"
            },
            {
              "icon": "",
              "label": "ทั้งคีย์และค่าได้รับการตรวจสอบ"
            },
            {
              "icon": "",
              "label": "ไม่มีเลย — `in` บน dict เพิ่มเติม TypeError เสมอ"
            },
            {
              "icon": "",
              "label": "คีย์ — `in` บน dictionary ทดสอบสมาชิกในคีย์ของมัน ไม่ใช่ค่า"
            }
          ]
        },
        {
          "question": "`names = ['Al', 'Bo']` และ `scores = [10, 20]` สิ่งที่ `list(zip(names, scores))` ส่งคืนคืออะไร",
          "options": [
            {
              "icon": "",
              "label": "`[('Al', 'Bo'), (10, 20)]`"
            },
            {
              "icon": "",
              "label": "`['Al', 10, 'Bo', 20]`"
            },
            {
              "icon": "",
              "label": "`[('Al', 10), ('Bo', 20)]`"
            },
            {
              "icon": "",
              "label": "ValueError เพราะ `zip` ต้องการสามอาร์กิวเมนต์หรือมากกว่า"
            }
          ]
        },
        {
          "question": "`class Dog: tricks = []` ถือรายการระดับคลาส และ `add_trick` เพิ่มเติมเป็น `self.tricks` `d1 = Dog()` และ `d2 = Dog()` ถูกสร้าง จากนั้น `d1.add_trick('sit')` ทำงาน `d2.tricks` มีอะไร",
          "options": [
            {
              "icon": "",
              "label": "`[]` — แต่ละอินสแตนซ์ได้รับสำเนาที่เป็นอิสระของ tricks"
            },
            {
              "icon": "",
              "label": "`['sit']` — `tricks` คือรายการระดับคลาสแบ่งปันโดยอินสแตนซ์ทุกอัน ดังนั้นการเปลี่ยนแปลงของ d1 จึงมองเห็นได้บน d2 ด้วย"
            },
            {
              "icon": "",
              "label": "TypeError — อินสแตนซ์ไม่สามารถเพิ่มเติมให้กับแอตทริบิวต์คลาส"
            },
            {
              "icon": "",
              "label": "`['sit']` เพียงหลังจาก `d2 = Dog()` ถูก re-run"
            }
          ]
        },
        {
          "question": "`class A` มี `def greet(self): return 'A'` `class B(A)` มี `def greet(self): return 'B' + super().greet()` `B().greet()` ส่งคืนอะไร",
          "options": [
            {
              "icon": "",
              "label": "`'AB'` — `super()` ทำงานก่อนโค้ดของคลาสย่อยเสมอ"
            },
            {
              "icon": "",
              "label": "`'B'` — `super().greet()` ถูกละเว้นเพราะ B ปฏิเสธ greet แล้ว"
            },
            {
              "icon": "",
              "label": "`'BA'` — `super().greet()` เรียกเมธอด A และผลลัพธ์ของมันจะถูกต่อท้าย 'B'"
            },
            {
              "icon": "",
              "label": "AttributeError เพราะ A ไม่มี greet วิธีที่มองเห็นได้สำหรับ B"
            }
          ]
        },
        {
          "question": "`class Point` จัดเก็บ `self.x` ใน `__init__` และไม่กำหนดเมธอดอื่น `p1 = Point(1)` และ `p2 = Point(1)` `p1 == p2` ส่งคืนอะไรโดยค่าเริ่มต้น",
          "options": [
            {
              "icon": "",
              "label": "True — Python เปรียบเทียบแอตทริบิวต์ที่ตรงกันทั้งหมดโดยค่าเริ่มต้น"
            },
            {
              "icon": "",
              "label": "False — โดยไม่มี `__eq__` ที่กำหนดเอง `==` ตรวจสอบกลับไปยังการเปรียบเทียบข้อมูลประจำตัว และ p1 และ p2 คือ อบเจกต์ที่แตกต่างกัน"
            },
            {
              "icon": "",
              "label": "True เพราะเท่านั้นทั้งสองอบเจกต์ถูกสร้างด้วยอาร์กิวเมนต์เดียวกัน"
            },
            {
              "icon": "",
              "label": "TypeError เพราะ Point ไม่กำหนด `__eq__`"
            }
          ]
        },
        {
          "question": "ประโยค except ใดด้านล่างจะจับ ZeroDivisionError ด้วย: `except ArithmeticError` `except ValueError` หรือ `except KeyError`",
          "options": [
            {
              "icon": "",
              "label": "`except ValueError` — ข้อผิดพลาดการหารถือว่าเป็นค่าที่ไม่ถูกต้อง"
            },
            {
              "icon": "",
              "label": "`except KeyError` — ข้อผิดพลาด runtime ใด ๆ ที่ไม่ผูกพันกับประเภทเฉพาะจะตรวจสอบกลับไปยัง KeyError"
            },
            {
              "icon": "",
              "label": "ไม่มีเลย — มีเพียง `except ZeroDivisionError` เท่านั้นที่สามารถจับได้"
            },
            {
              "icon": "",
              "label": "`except ArithmeticError` — ZeroDivisionError คือคลาสย่อยของ ArithmeticError"
            }
          ]
        },
        {
          "question": "คุณเปิดไฟล์ด้วย `open('data.txt') as f:` และข้อยกเว้นจะเพิ่มขึ้นขณะอ่านภายในบล็อก ไฟล์ยังคงปิดอยู่หรือไม่",
          "options": [
            {
              "icon": "",
              "label": "ไม่ — ไฟล์อยู่เปิดเพราะบล็อกไม่ได้เสร็จสิ้นตามปกติ"
            },
            {
              "icon": "",
              "label": "เพียงถ้าคุณเพิ่มประโยค `finally` รอบ `with` statement"
            },
            {
              "icon": "",
              "label": "ใช่ — `with` statement เรียกวิธี `__exit__` ของไฟล์ ซึ่งปิดมัน แม้ว่าข้อยกเว้นจะเกิดขึ้นภายในบล็อก"
            },
            {
              "icon": "",
              "label": "ขึ้นอยู่กับประเภทข้อยกเว้น — เพียงข้อยกเว้นที่จับได้ที่อื่นจะทริกเกอร์การทำความสะอาด"
            }
          ]
        },
        {
          "question": "`x = [3, 1, 2]` และ `y = x.sort()` `y` ถือเก็บอะไร",
          "options": [
            {
              "icon": "",
              "label": "`[1, 2, 3]` — `sort()` ส่งคืนรายการที่เรียงลำดับใหม่"
            },
            {
              "icon": "",
              "label": "None — `list.sort()` เรียงลำดับในที่และส่งคืน None; x เอง กลายเป็น `[1, 2, 3]`"
            },
            {
              "icon": "",
              "label": "`[3, 1, 2]` — `sort()` ส่งคืนรายการเรียงลำดับเดิมและเปลี่ยนลำดับภายในของ x เท่านั้น"
            },
            {
              "icon": "",
              "label": "TypeError เพราะ `sort()` ไม่สามารถกำหนดให้ตัวแปรได้"
            }
          ]
        },
        {
          "question": "จะเกิดอะไรขึ้นเมื่อคุณเรียก `'Score: ' + 42`",
          "options": [
            {
              "icon": "",
              "label": "`'Score: 42'` — Python แปลงตัวเลขโดยอัตโนมัติภายใน `+` นิพจน์"
            },
            {
              "icon": "",
              "label": "`'Score: '` — ตัวเลขถูกวางโดยเงียบ"
            },
            {
              "icon": "",
              "label": "42 — สตริงถูกบังคับให้เป็นตัวเลขและเพิ่ม"
            },
            {
              "icon": "",
              "label": "TypeError — คุณไม่สามารถต่อสตริงและ int โดยตรง 42 ต้องแปลงด้วย `str()` ก่อน"
            }
          ]
        },
        {
          "question": "คุณต้องตรวจสอบว่าลิสต์ที่เรียก results ว่างหรือไม่ วิธี idiomatic Python คืออะไร: `if results == []:` `if len(results) == 0:` หรือ `if not results:`",
          "options": [
            {
              "icon": "",
              "label": "`if results == []:` — นี่เป็นวิธีที่เชื่อถือได้เพียงวิธีเดียวในการตรวจจับรายการเปล่า"
            },
            {
              "icon": "",
              "label": "`if len(results) == 0:` — นี่จำเป็นเพราะรายการเปล่าเป็นจริงใน Python"
            },
            {
              "icon": "",
              "label": "ทั้งสามไม่เคยใช้ในทางปฏิบัติ วิธี มาตรฐานคือ `if results is None:`"
            },
            {
              "icon": "",
              "label": "`if not results:` — idiom Python อาศัยความเป็นจริง และรายการเปล่าเป็นเท็จ"
            }
          ]
        }
      ],
      "optionOrderVersion": "92945565db6c55da"
    }
  }
}
