{
  "assessmentTests": {
    "python_test": {
      "name": "Python 테스트",
      "desc": "구문, 함수, 데이터 구조 및 객체 동작에 관한 30개의 시나리오 문제입니다. 당신의 Python 실력이 채용공고에서 말하는 Python 능력에 부합하는지 확인하세요.",
      "recommendation": "당신의 Python 기술 프로필",
      "results": {
        "beginner": {
          "name": "초급자",
          "desc": "짧은 스크립트를 따라 실행하고 값을 수정할 수 있지만, 놓친 문제들은 Python만의 특수한 동작 방식 때문입니다. 예를 들어, 기본값이 한 번만 만들어지고 재사용되는 특성, is와 ==의 차이, 함수 내에서 변수를 할당하는 순간 그 변수가 지역변수가 되는 현상 같은 것들입니다. 이것들은 프로그래밍을 못해서가 아니라 다른 언어에서 온 사람들도 자주 헷갈리는 Python 특화 규칙입니다. 이런 것들은 코드가 언뜻 맞아 보이는데도 버그가 숨어있는 곳이기 때문에 직장에서 중요합니다.",
          "recommendation": "이 세 가지부터 시작하세요 (이 순서대로): 가변 기본값 인수 (basket=[]이 위험한 이유), is와 ==의 차이, 함수 내의 변수 범위 설정 방법. 공식 Python 튜토리얼 (docs.python.org)에서 세 가지 모두 직접 다루고 있고, \"Python gotchas\"라는 검색어로 각각의 실제 사용 예제를 찾을 수 있습니다."
        },
        "intermediate": {
          "name": "중급자",
          "desc": "일상적인 스크립팅을 편하게 다루며, 데이터 구조, 제어 흐름, 기본 함수를 잘 이해합니다. 기존 코드베이스에서 루틴 유지보수나 작은 기능 추가 작업으로 인해 느려질 일은 없을 것입니다. 여기서 고급 수준까지의 격차는 주로 Python의 편의 기능들이 서로 상호작용할 때 일어나는 문제들입니다. 예를 들어, 얕은 복사가 중첩된 데이터를 공유하게 두어 당신이 예상한 복제가 되지 않는 경우, 제너레이터의 반환값이 자신의 출력에 조용히 포함되지 않는 경우, 데코레이터가 쌓이는 순서를 잘못 이해하는 경우 같은 것들입니다. 이런 종류의 버그는 경력 많은 리뷰어라면 10초 안에 지적하지만, 다른 사람들은 한 시간이나 들여 찾습니다.",
          "recommendation": "객체와 반복 내부에 집중하세요: 얕은 복사 vs 깊은 복사, 제너레이터가 실제로 반환값을 어떻게 처리하는지, 데코레이터 스택의 순서 작동 방식. 그다음 대부분의 튜토리얼이 건너뛰는 클래스 기본 사항들 - 커스텀 __eq__ 없이의 기본 동등성, 가변 클래스 속성이 모든 인스턴스에서 공유되는 이유."
        },
        "advanced": {
          "name": "고급자",
          "desc": "대부분의 채용공고가 \"강한 Python\"이라고 말할 때 의미하는 수준입니다. 이 수준에서는 올바른 도구를 직관적으로 선택할 수 있고, 공유 상태가 왜 변했는지 알며, 다른 사람의 함수를 읽고 그 출력값을 정확히 예측할 수 있습니다. 이 등급과 최상위 등급을 구분하는 것은 방어적 작업입니다. 즉, 클래스 속성, 키워드 전용 인수, 예외 계층이 관련되었을 때 두 가지 올바른 방법 중 어느 것이 오작동하는지 아는 것입니다.",
          "recommendation": "다른 사람도 만지는 코드베이스를 보호하는 부분들로 진출하세요: 키워드 전용 인수를 문법 호기심이 아닌 API 설계 선택으로 이해하기, 예외 계층 (except 절이 한 클래스만이 아니라 올바른 오류 계열을 잡도록), context manager를 정리를 보장하는 표준 방식으로 이해하기. 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, is는 False - 내용은 같지만 메모리 상의 다른 객체입니다"
            },
            {
              "icon": "",
              "label": "둘 다 False - 분리된 리터럴은 Python에서 절대 같지 않습니다"
            },
            {
              "icon": "",
              "label": "is는 True, ==는 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 - 두 연산자 모두 Python 3에서 float를 반환합니다"
            },
            {
              "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-문자열은 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 - falsy 값만 포함하는 리스트는 falsy입니다"
            },
            {
              "icon": "",
              "label": "False, 그 다음 True - 빈 리스트는 falsy이고, 한 개의 원소(0이라도)를 포함하는 리스트는 truthy입니다"
            },
            {
              "icon": "",
              "label": "둘 다 True - None이 아닌 객체는 항상 truthy입니다"
            },
            {
              "icon": "",
              "label": "True, 그 다음 False - 리스트는 비어있을 때만 truthy입니다"
            }
          ]
        },
        {
          "question": "모듈 레벨에서 count = 0이 존재합니다. def increment() 내에서는 count += 1; return count를 정의하고, increment()를 호출합니다. 무슨 일이 일어날까요?",
          "options": [
            {
              "icon": "",
              "label": "UnboundLocalError - 함수 내 어디든 count에 할당하면 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] - lambda는 항상 변수에 할당된 첫 번째 값을 캡처합니다"
            },
            {
              "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는 시그니처의 bare * 뒤에 있어서 키워드로 전달해야 합니다"
            },
            {
              "icon": "",
              "label": "f(1, 2) - 위치 인수는 *에 관계없이 왼쪽에서 오른쪽으로 매개변수를 채웁니다"
            },
            {
              "icon": "",
              "label": "f(a=1, 2) - 키워드 인수가 먼저 와야 합니다"
            },
            {
              "icon": "",
              "label": "f(1) - b는 *뒤에 있어서 선택적입니다"
            }
          ]
        },
        {
          "question": "제너레이터 함수는 1을 yield하고, 2를 yield하고, return 99를 합니다. list(the_generator())는 무엇을 포함하고, 99는 어떻게 될까요?",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 99] - 제너레이터 내 return은 또 다른 yield처럼 동작합니다"
            },
            {
              "icon": "",
              "label": "[99] - return은 이미 yield된 값들을 즉시 무시합니다"
            },
            {
              "icon": "",
              "label": "[1, 2] - 제너레이터의 반환값은 제너레이터가 발생시키는 StopIteration에 첨부된 값이 되며, yield되지 않습니다"
            },
            {
              "icon": "",
              "label": "RuntimeError - 제너레이터는 return 문을 포함할 수 없습니다"
            }
          ]
        },
        {
          "question": "outer() 함수에서 x = 1이 설정되고, 중첩된 inner()는 nonlocal x; x += 1을 실행합니다. outer()가 inner()를 호출한 후 x를 반환합니다. outer()는 무엇을 반환할까요?",
          "options": [
            {
              "icon": "",
              "label": "1 - inner()는 x의 자신의 지역 복사본에서 작동하므로 변경이 지속되지 않습니다"
            },
            {
              "icon": "",
              "label": "UnboundLocalError - nonlocal 문 전에 x가 inner() 내에서 선언되지 않았습니다"
            },
            {
              "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": "둘 다 작동합니다 - 튜플에 리스트를 중첩하면 전체 튜플이 가변입니다"
            },
            {
              "icon": "",
              "label": "둘 다 TypeError를 발생시킵니다 - 튜플 내의 아무것도 절대 변경될 수 없습니다"
            },
            {
              "icon": "",
              "label": "t[2].append(5)는 TypeError를 발생시키지만 t[0] = 10은 튜플의 첫 번째 원소 재할당이 허용되기 때문에 작동합니다"
            },
            {
              "icon": "",
              "label": "t[2].append(5)는 리스트가 가변이기 때문에 작동합니다. t[0] = 10은 튜플 자체가 불변이기 때문에 TypeError를 발생시킵니다"
            }
          ]
        },
        {
          "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)) - 이것이 제너레이터 표현식입니다"
            },
            {
              "icon": "",
              "label": "대괄호가 있는 것 - 리스트 이해식은 Python 3에서 항상 게으릅니다"
            },
            {
              "icon": "",
              "label": "둘 다 게으릅니다 - 유일한 차이는 마지막에 반환되는 타입입니다"
            },
            {
              "icon": "",
              "label": "어느 것도 아닙니다 - 둘 다 전체 시퀀스를 즉시 메모리에 구성합니다"
            }
          ]
        },
        {
          "question": "try 블록이 0으로 나누고, except ZeroDivisionError 절이 'a'를 출력하고, finally 절이 'b'를 출력합니다. 무엇이 인쇄되고 어떤 순서일까요?",
          "options": [
            {
              "icon": "",
              "label": "b 그 다음 a - finally는 항상 except 절 전에 실행됩니다"
            },
            {
              "icon": "",
              "label": "a 그 다음 b - 일치하는 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": "예 - 하지만 deepcopy 인수 없이 copy.copy()가 호출되었기 때문일 뿐입니다"
            },
            {
              "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`은 항상 TypeError를 발생시킵니다"
            },
            {
              "icon": "",
              "label": "키 - 딕셔너리의 `in`은 값이 아닌 키 사이의 멤버십을 테스트합니다"
            }
          ]
        },
        {
          "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은 3개 이상의 인수를 요구합니다"
            }
          ]
        },
        {
          "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()가 다시 실행된 후에만"
            }
          ]
        },
        {
          "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는 B에 보이는 greet 메서드가 없습니다"
            }
          ]
        },
        {
          "question": "class Point는 __init__에서 self.x를 저장하고 다른 메서드는 정의하지 않습니다. 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 - 특정 타입과 연결되지 않은 모든 런타임 오류는 KeyError로 폴백합니다"
            },
            {
              "icon": "",
              "label": "아무것도 없습니다 - except ZeroDivisionError 자체만 캡처할 수 있습니다"
            },
            {
              "icon": "",
              "label": "except ArithmeticError - ZeroDivisionError는 ArithmeticError의 서브클래스입니다"
            }
          ]
        },
        {
          "question": "open('data.txt') as f:로 파일을 열고, 블록 내에서 읽는 중에 예외가 발생합니다. 파일은 여전히 닫혀있을까요?",
          "options": [
            {
              "icon": "",
              "label": "아니오 - 블록이 정상적으로 종료되지 않았으므로 파일은 열려있습니다"
            },
            {
              "icon": "",
              "label": "with 문 주위에 finally 절을 추가하는 경우에만"
            },
            {
              "icon": "",
              "label": "예 - with 문은 파일의 __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 - str과 int를 직접 연결할 수 없습니다. 42는 str()로 변환해야 합니다"
            }
          ]
        },
        {
          "question": "results라는 리스트가 비어있는지 확인해야 합니다. 관용적인 Python 방식은 다음 중 어느 것일까요: if results == []: , if len(results) == 0: , 아니면 if not results: ?",
          "options": [
            {
              "icon": "",
              "label": "if results == []: - 이것만이 빈 리스트를 감지하는 유일한 신뢰할 수 있는 방법입니다"
            },
            {
              "icon": "",
              "label": "if len(results) == 0: - Python에서 빈 리스트가 truthy이기 때문에 이것이 필요합니다"
            },
            {
              "icon": "",
              "label": "세 가지 모두 실제로 사용되지 않습니다. 표준 방법은 if results is None:입니다"
            },
            {
              "icon": "",
              "label": "if not results: - Python 관용구는 진실성에 의존하며 빈 리스트는 falsy입니다"
            }
          ]
        }
      ],
      "optionOrderVersion": "92945565db6c55da"
    }
  }
}
