[{"data":1,"prerenderedAt":2924},["ShallowReactive",2],{"page-\u002Fpython\u002F01-introduction-and-setup":3},{"id":4,"title":5,"body":6,"description":27,"extension":2918,"meta":2919,"navigation":63,"path":2920,"seo":2921,"stem":2922,"__hash__":2923},"content\u002Fpython\u002F01-introduction-and-setup.md","01 — Introduction & Setup",{"type":7,"value":8,"toc":2897},"minimark",[9,13,18,344,542,547,614,618,993,997,1275,1355,1359,1367,1378,1481,1485,1492,1513,1615,1619,1638,1705,1709,1733,1756,1767,1770,1809,1885,1962,1965,2016,2020,2089,2395,2399,2503,2507,2592,2596,2711,2715,2722,2782,2853,2857,2893],[10,11,5],"h1",{"id":12},"_01-introduction-setup",[14,15,17],"h2",{"id":16},"execution-model-source-bytecode-vm","Execution Model: Source → Bytecode → VM",[19,20,22],"code-wrapper",{"language":21},"python",[23,24,28],"pre",{"className":25,"code":26,"language":21,"meta":27,"style":27},"language-python shiki shiki-themes github-light github-dark","# CPython's execution pipeline, observable from pure Python:\n# 1. Source (.py) → compiler → bytecode (platform-independent .pyc)\n# 2. Bytecode → CPython VM eval loop → execution\n# 3. .pyc cached in __pycache__\u002F to skip step 1 on subsequent imports\n\nimport dis, sys, types\n\n# Compile a function and inspect its bytecode — this is what the VM actually executes\ndef pipeline_example(data: list[int]) -> int:\n    total = 0\n    for item in data:\n        if item > 0:                    # POP_JUMP_IF_FALSE branches at bytecode level\n            total += item               # BINARY_OP in-place add\n    return total\n\n# disassembles to CPython bytecode — each line is one VM instruction\ndis.dis(pipeline_example)\n#  2           0 RESUME                   0      ← 3.11+ opcode, coroutine-aware entry\n#  3           2 LOAD_CONST               1 (0)  ← push literal 0 onto value stack\n#              4 STORE_FAST               1 (total) ← store into fast local slot 1\n#  4           6 LOAD_FAST                1 (total) ← load local for loop init\n#  ... (full output shows LOAD_FAST, BINARY_OP, POP_JUMP_IF_FALSE, JUMP_BACKWARD)\n\n# The bytecode object itself is a real object you can inspect\ncode = pipeline_example.__code__\nprint(f\"argcount={code.co_argcount}, varnames={code.co_varnames}\")\nprint(f\"stacksize={code.co_stacksize}  ← max value-stack depth the VM needs\")\nprint(f\"consts={code.co_consts}  ← literals folded into the code object at compile time\")\n","",[29,30,31,40,46,52,58,65,76,81,87,112,124,139,159,174,183,188,194,200,206,212,218,224,230,235,241,255,296,320],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","# CPython's execution pipeline, observable from pure Python:\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"# 1. Source (.py) → compiler → bytecode (platform-independent .pyc)\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"# 2. Bytecode → CPython VM eval loop → execution\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"# 3. .pyc cached in __pycache__\u002F to skip step 1 on subsequent imports\n",[32,59,61],{"class":34,"line":60},5,[32,62,64],{"emptyLinePlaceholder":63},true,"\n",[32,66,68,72],{"class":34,"line":67},6,[32,69,71],{"class":70},"svdQ7","import",[32,73,75],{"class":74},"ssxIu"," dis, sys, types\n",[32,77,79],{"class":34,"line":78},7,[32,80,64],{"emptyLinePlaceholder":63},[32,82,84],{"class":34,"line":83},8,[32,85,86],{"class":38},"# Compile a function and inspect its bytecode — this is what the VM actually executes\n",[32,88,90,93,97,100,104,107,109],{"class":34,"line":89},9,[32,91,92],{"class":70},"def",[32,94,96],{"class":95},"sIsaT"," pipeline_example",[32,98,99],{"class":74},"(data: list[",[32,101,103],{"class":102},"snvgF","int",[32,105,106],{"class":74},"]) -> ",[32,108,103],{"class":102},[32,110,111],{"class":74},":\n",[32,113,115,118,121],{"class":34,"line":114},10,[32,116,117],{"class":74},"    total ",[32,119,120],{"class":70},"=",[32,122,123],{"class":102}," 0\n",[32,125,127,130,133,136],{"class":34,"line":126},11,[32,128,129],{"class":70},"    for",[32,131,132],{"class":74}," item ",[32,134,135],{"class":70},"in",[32,137,138],{"class":74}," data:\n",[32,140,142,145,147,150,153,156],{"class":34,"line":141},12,[32,143,144],{"class":70},"        if",[32,146,132],{"class":74},[32,148,149],{"class":70},">",[32,151,152],{"class":102}," 0",[32,154,155],{"class":74},":                    ",[32,157,158],{"class":38},"# POP_JUMP_IF_FALSE branches at bytecode level\n",[32,160,162,165,168,171],{"class":34,"line":161},13,[32,163,164],{"class":74},"            total ",[32,166,167],{"class":70},"+=",[32,169,170],{"class":74}," item               ",[32,172,173],{"class":38},"# BINARY_OP in-place add\n",[32,175,177,180],{"class":34,"line":176},14,[32,178,179],{"class":70},"    return",[32,181,182],{"class":74}," total\n",[32,184,186],{"class":34,"line":185},15,[32,187,64],{"emptyLinePlaceholder":63},[32,189,191],{"class":34,"line":190},16,[32,192,193],{"class":38},"# disassembles to CPython bytecode — each line is one VM instruction\n",[32,195,197],{"class":34,"line":196},17,[32,198,199],{"class":74},"dis.dis(pipeline_example)\n",[32,201,203],{"class":34,"line":202},18,[32,204,205],{"class":38},"#  2           0 RESUME                   0      ← 3.11+ opcode, coroutine-aware entry\n",[32,207,209],{"class":34,"line":208},19,[32,210,211],{"class":38},"#  3           2 LOAD_CONST               1 (0)  ← push literal 0 onto value stack\n",[32,213,215],{"class":34,"line":214},20,[32,216,217],{"class":38},"#              4 STORE_FAST               1 (total) ← store into fast local slot 1\n",[32,219,221],{"class":34,"line":220},21,[32,222,223],{"class":38},"#  4           6 LOAD_FAST                1 (total) ← load local for loop init\n",[32,225,227],{"class":34,"line":226},22,[32,228,229],{"class":38},"#  ... (full output shows LOAD_FAST, BINARY_OP, POP_JUMP_IF_FALSE, JUMP_BACKWARD)\n",[32,231,233],{"class":34,"line":232},23,[32,234,64],{"emptyLinePlaceholder":63},[32,236,238],{"class":34,"line":237},24,[32,239,240],{"class":38},"# The bytecode object itself is a real object you can inspect\n",[32,242,244,247,249,252],{"class":34,"line":243},25,[32,245,246],{"class":74},"code ",[32,248,120],{"class":70},[32,250,251],{"class":74}," pipeline_example.",[32,253,254],{"class":102},"__code__\n",[32,256,258,261,264,267,271,274,277,280,283,285,288,290,293],{"class":34,"line":257},26,[32,259,260],{"class":102},"print",[32,262,263],{"class":74},"(",[32,265,266],{"class":70},"f",[32,268,270],{"class":269},"sJ6F3","\"argcount=",[32,272,273],{"class":102},"{",[32,275,276],{"class":74},"code.co_argcount",[32,278,279],{"class":102},"}",[32,281,282],{"class":269},", varnames=",[32,284,273],{"class":102},[32,286,287],{"class":74},"code.co_varnames",[32,289,279],{"class":102},[32,291,292],{"class":269},"\"",[32,294,295],{"class":74},")\n",[32,297,299,301,303,305,308,310,313,315,318],{"class":34,"line":298},27,[32,300,260],{"class":102},[32,302,263],{"class":74},[32,304,266],{"class":70},[32,306,307],{"class":269},"\"stacksize=",[32,309,273],{"class":102},[32,311,312],{"class":74},"code.co_stacksize",[32,314,279],{"class":102},[32,316,317],{"class":269},"  ← max value-stack depth the VM needs\"",[32,319,295],{"class":74},[32,321,323,325,327,329,332,334,337,339,342],{"class":34,"line":322},28,[32,324,260],{"class":102},[32,326,263],{"class":74},[32,328,266],{"class":70},[32,330,331],{"class":269},"\"consts=",[32,333,273],{"class":102},[32,335,336],{"class":74},"code.co_consts",[32,338,279],{"class":102},[32,340,341],{"class":269},"  ← literals folded into the code object at compile time\"",[32,343,295],{"class":74},[19,345,346],{"language":21},[23,347,349],{"className":25,"code":348,"language":21,"meta":27,"style":27},"# Production-grade: a bytecode-level hot-path analyzer\n# Walks a function's code object to count specific opcodes — useful for\n# understanding why a \"simple\" function is slow without a full profiler\n\nimport dis\nfrom collections import Counter\n\ndef opcode_profile(func):\n    \"\"\"Count VM opcodes in a function — reveals hidden overhead in 'simple' code.\"\"\"\n    counts = Counter()\n    for instr in dis.get_instructions(func):\n        counts[instr.opname] += 1\n    return counts\n\ndef naive_sum(data):\n    total = 0\n    for x in data:\n        total += x          # LOAD_FAST + LOAD_CONST + BINARY_OP + STORE_FAST per iteration\n    return total\n\nprofile = opcode_profile(naive_sum)\n# Each loop iteration = ~4 opcodes × N iterations — this is why pure-Python\n# loops are O(N) bytecode dispatches while sum(data) is a single C call\nprint(profile.most_common(5))\n# [('LOAD_FAST', ...), ('STORE_FAST', ...), ('BINARY_OP', ...), ...]\n",[29,350,351,356,361,366,370,377,390,394,404,409,419,431,441,448,452,462,470,481,494,500,504,514,519,524,537],{"__ignoreMap":27},[32,352,353],{"class":34,"line":35},[32,354,355],{"class":38},"# Production-grade: a bytecode-level hot-path analyzer\n",[32,357,358],{"class":34,"line":42},[32,359,360],{"class":38},"# Walks a function's code object to count specific opcodes — useful for\n",[32,362,363],{"class":34,"line":48},[32,364,365],{"class":38},"# understanding why a \"simple\" function is slow without a full profiler\n",[32,367,368],{"class":34,"line":54},[32,369,64],{"emptyLinePlaceholder":63},[32,371,372,374],{"class":34,"line":60},[32,373,71],{"class":70},[32,375,376],{"class":74}," dis\n",[32,378,379,382,385,387],{"class":34,"line":67},[32,380,381],{"class":70},"from",[32,383,384],{"class":74}," collections ",[32,386,71],{"class":70},[32,388,389],{"class":74}," Counter\n",[32,391,392],{"class":34,"line":78},[32,393,64],{"emptyLinePlaceholder":63},[32,395,396,398,401],{"class":34,"line":83},[32,397,92],{"class":70},[32,399,400],{"class":95}," opcode_profile",[32,402,403],{"class":74},"(func):\n",[32,405,406],{"class":34,"line":89},[32,407,408],{"class":269},"    \"\"\"Count VM opcodes in a function — reveals hidden overhead in 'simple' code.\"\"\"\n",[32,410,411,414,416],{"class":34,"line":114},[32,412,413],{"class":74},"    counts ",[32,415,120],{"class":70},[32,417,418],{"class":74}," Counter()\n",[32,420,421,423,426,428],{"class":34,"line":126},[32,422,129],{"class":70},[32,424,425],{"class":74}," instr ",[32,427,135],{"class":70},[32,429,430],{"class":74}," dis.get_instructions(func):\n",[32,432,433,436,438],{"class":34,"line":141},[32,434,435],{"class":74},"        counts[instr.opname] ",[32,437,167],{"class":70},[32,439,440],{"class":102}," 1\n",[32,442,443,445],{"class":34,"line":161},[32,444,179],{"class":70},[32,446,447],{"class":74}," counts\n",[32,449,450],{"class":34,"line":176},[32,451,64],{"emptyLinePlaceholder":63},[32,453,454,456,459],{"class":34,"line":185},[32,455,92],{"class":70},[32,457,458],{"class":95}," naive_sum",[32,460,461],{"class":74},"(data):\n",[32,463,464,466,468],{"class":34,"line":190},[32,465,117],{"class":74},[32,467,120],{"class":70},[32,469,123],{"class":102},[32,471,472,474,477,479],{"class":34,"line":196},[32,473,129],{"class":70},[32,475,476],{"class":74}," x ",[32,478,135],{"class":70},[32,480,138],{"class":74},[32,482,483,486,488,491],{"class":34,"line":202},[32,484,485],{"class":74},"        total ",[32,487,167],{"class":70},[32,489,490],{"class":74}," x          ",[32,492,493],{"class":38},"# LOAD_FAST + LOAD_CONST + BINARY_OP + STORE_FAST per iteration\n",[32,495,496,498],{"class":34,"line":208},[32,497,179],{"class":70},[32,499,182],{"class":74},[32,501,502],{"class":34,"line":214},[32,503,64],{"emptyLinePlaceholder":63},[32,505,506,509,511],{"class":34,"line":220},[32,507,508],{"class":74},"profile ",[32,510,120],{"class":70},[32,512,513],{"class":74}," opcode_profile(naive_sum)\n",[32,515,516],{"class":34,"line":226},[32,517,518],{"class":38},"# Each loop iteration = ~4 opcodes × N iterations — this is why pure-Python\n",[32,520,521],{"class":34,"line":232},[32,522,523],{"class":38},"# loops are O(N) bytecode dispatches while sum(data) is a single C call\n",[32,525,526,528,531,534],{"class":34,"line":237},[32,527,260],{"class":102},[32,529,530],{"class":74},"(profile.most_common(",[32,532,533],{"class":102},"5",[32,535,536],{"class":74},"))\n",[32,538,539],{"class":34,"line":243},[32,540,541],{"class":38},"# [('LOAD_FAST', ...), ('STORE_FAST', ...), ('BINARY_OP', ...), ...]\n",[543,544,546],"h3",{"id":545},"implementation-landscape","Implementation Landscape",[548,549,550,566],"table",{},[551,552,553],"thead",{},[554,555,556,560,563],"tr",{},[557,558,559],"th",{},"Implementation",[557,561,562],{},"Engine",[557,564,565],{},"Use Case",[567,568,569,584,597],"tbody",{},[554,570,571,578,581],{},[572,573,574],"td",{},[575,576,577],"strong",{},"CPython",[572,579,580],{},"C interpreter, no JIT (3.13 adds experimental JIT)",[572,582,583],{},"Default — the reference implementation. All examples here target CPython 3.11+.",[554,585,586,591,594],{},[572,587,588],{},[575,589,590],{},"PyPy",[572,592,593],{},"RPython JIT, 4–10× faster on long-running pure-Python",[572,595,596],{},"CPU-bound workloads without heavy C-extension dependencies.",[554,598,599,604,607],{},[572,600,601],{},[575,602,603],{},"MicroPython",[572,605,606],{},"Lean interpreter for embedded",[572,608,609,610,613],{},"ESP32, Raspberry Pi Pico — restricted stdlib, no ",[29,611,612],{},"asyncio"," in full form.",[543,615,617],{"id":616},"the-gil-architectural-constraint-not-a-bug","The GIL — architectural constraint, not a bug",[19,619,620],{"language":21},[23,621,623],{"className":25,"code":622,"language":21,"meta":27,"style":27},"# The GIL (Global Interpreter Lock) means only ONE thread executes CPython\n# bytecode at any instant — even on a 64-core machine. This is because\n# CPython's reference counting (refcount in every PyObject header) is not\n# thread-safe without a global lock.\n#\n# Consequence: threading gives NO speedup for CPU-bound pure Python.\n# Use multiprocessing (separate interpreters, separate GILs) for CPU parallelism.\n# Use threading\u002Fasyncio for I\u002FO-bound work (GIL released during I\u002FO waits).\n\nimport threading, time, multiprocessing as mp\n\ndef cpu_bound(n):\n    return sum(i * i for i in range(n))\n\nif __name__ == \"__main__\":\n    N = 20_000_000\n\n    # Sequential baseline\n    t0 = time.perf_counter(); cpu_bound(N); cpu_bound(N)\n    print(f\"sequential: {time.perf_counter() - t0:.2f}s\")\n\n    # Threading — NO parallelism for CPU-bound work (GIL serializes)\n    t0 = time.perf_counter()\n    threads = [threading.Thread(target=cpu_bound, args=(N,)) for _ in range(2)]\n    for t in threads: t.start()\n    for t in threads: t.join()\n    print(f\"2 threads (CPU-bound): {time.perf_counter() - t0:.2f}s  ← ~same as sequential\")\n\n    # Multiprocessing — TRUE parallelism (separate processes, separate GILs)\n    t0 = time.perf_counter()\n    with mp.Pool(2) as pool:\n        pool.map(cpu_bound, [N, N])\n    print(f\"2 processes (CPU-bound): {time.perf_counter() - t0:.2f}s  ← ~half\")\n",[29,624,625,630,635,640,645,650,655,660,665,669,682,686,696,725,729,745,755,759,764,774,807,811,816,825,869,881,892,920,924,930,939,958,964],{"__ignoreMap":27},[32,626,627],{"class":34,"line":35},[32,628,629],{"class":38},"# The GIL (Global Interpreter Lock) means only ONE thread executes CPython\n",[32,631,632],{"class":34,"line":42},[32,633,634],{"class":38},"# bytecode at any instant — even on a 64-core machine. This is because\n",[32,636,637],{"class":34,"line":48},[32,638,639],{"class":38},"# CPython's reference counting (refcount in every PyObject header) is not\n",[32,641,642],{"class":34,"line":54},[32,643,644],{"class":38},"# thread-safe without a global lock.\n",[32,646,647],{"class":34,"line":60},[32,648,649],{"class":38},"#\n",[32,651,652],{"class":34,"line":67},[32,653,654],{"class":38},"# Consequence: threading gives NO speedup for CPU-bound pure Python.\n",[32,656,657],{"class":34,"line":78},[32,658,659],{"class":38},"# Use multiprocessing (separate interpreters, separate GILs) for CPU parallelism.\n",[32,661,662],{"class":34,"line":83},[32,663,664],{"class":38},"# Use threading\u002Fasyncio for I\u002FO-bound work (GIL released during I\u002FO waits).\n",[32,666,667],{"class":34,"line":89},[32,668,64],{"emptyLinePlaceholder":63},[32,670,671,673,676,679],{"class":34,"line":114},[32,672,71],{"class":70},[32,674,675],{"class":74}," threading, time, multiprocessing ",[32,677,678],{"class":70},"as",[32,680,681],{"class":74}," mp\n",[32,683,684],{"class":34,"line":126},[32,685,64],{"emptyLinePlaceholder":63},[32,687,688,690,693],{"class":34,"line":141},[32,689,92],{"class":70},[32,691,692],{"class":95}," cpu_bound",[32,694,695],{"class":74},"(n):\n",[32,697,698,700,703,706,709,712,715,717,719,722],{"class":34,"line":161},[32,699,179],{"class":70},[32,701,702],{"class":102}," sum",[32,704,705],{"class":74},"(i ",[32,707,708],{"class":70},"*",[32,710,711],{"class":74}," i ",[32,713,714],{"class":70},"for",[32,716,711],{"class":74},[32,718,135],{"class":70},[32,720,721],{"class":102}," range",[32,723,724],{"class":74},"(n))\n",[32,726,727],{"class":34,"line":176},[32,728,64],{"emptyLinePlaceholder":63},[32,730,731,734,737,740,743],{"class":34,"line":185},[32,732,733],{"class":70},"if",[32,735,736],{"class":102}," __name__",[32,738,739],{"class":70}," ==",[32,741,742],{"class":269}," \"__main__\"",[32,744,111],{"class":74},[32,746,747,750,752],{"class":34,"line":190},[32,748,749],{"class":74},"    N ",[32,751,120],{"class":70},[32,753,754],{"class":102}," 20_000_000\n",[32,756,757],{"class":34,"line":196},[32,758,64],{"emptyLinePlaceholder":63},[32,760,761],{"class":34,"line":202},[32,762,763],{"class":38},"    # Sequential baseline\n",[32,765,766,769,771],{"class":34,"line":208},[32,767,768],{"class":74},"    t0 ",[32,770,120],{"class":70},[32,772,773],{"class":74}," time.perf_counter(); cpu_bound(N); cpu_bound(N)\n",[32,775,776,779,781,783,786,788,791,794,797,800,802,805],{"class":34,"line":214},[32,777,778],{"class":102},"    print",[32,780,263],{"class":74},[32,782,266],{"class":70},[32,784,785],{"class":269},"\"sequential: ",[32,787,273],{"class":102},[32,789,790],{"class":74},"time.perf_counter() ",[32,792,793],{"class":70},"-",[32,795,796],{"class":74}," t0",[32,798,799],{"class":70},":.2f",[32,801,279],{"class":102},[32,803,804],{"class":269},"s\"",[32,806,295],{"class":74},[32,808,809],{"class":34,"line":220},[32,810,64],{"emptyLinePlaceholder":63},[32,812,813],{"class":34,"line":226},[32,814,815],{"class":38},"    # Threading — NO parallelism for CPU-bound work (GIL serializes)\n",[32,817,818,820,822],{"class":34,"line":232},[32,819,768],{"class":74},[32,821,120],{"class":70},[32,823,824],{"class":74}," time.perf_counter()\n",[32,826,827,830,832,835,839,841,844,847,849,852,854,857,859,861,863,866],{"class":34,"line":237},[32,828,829],{"class":74},"    threads ",[32,831,120],{"class":70},[32,833,834],{"class":74}," [threading.Thread(",[32,836,838],{"class":837},"sCrzJ","target",[32,840,120],{"class":70},[32,842,843],{"class":74},"cpu_bound, ",[32,845,846],{"class":837},"args",[32,848,120],{"class":70},[32,850,851],{"class":74},"(N,)) ",[32,853,714],{"class":70},[32,855,856],{"class":74}," _ ",[32,858,135],{"class":70},[32,860,721],{"class":102},[32,862,263],{"class":74},[32,864,865],{"class":102},"2",[32,867,868],{"class":74},")]\n",[32,870,871,873,876,878],{"class":34,"line":243},[32,872,129],{"class":70},[32,874,875],{"class":74}," t ",[32,877,135],{"class":70},[32,879,880],{"class":74}," threads: t.start()\n",[32,882,883,885,887,889],{"class":34,"line":257},[32,884,129],{"class":70},[32,886,875],{"class":74},[32,888,135],{"class":70},[32,890,891],{"class":74}," threads: t.join()\n",[32,893,894,896,898,900,903,905,907,909,911,913,915,918],{"class":34,"line":298},[32,895,778],{"class":102},[32,897,263],{"class":74},[32,899,266],{"class":70},[32,901,902],{"class":269},"\"2 threads (CPU-bound): ",[32,904,273],{"class":102},[32,906,790],{"class":74},[32,908,793],{"class":70},[32,910,796],{"class":74},[32,912,799],{"class":70},[32,914,279],{"class":102},[32,916,917],{"class":269},"s  ← ~same as sequential\"",[32,919,295],{"class":74},[32,921,922],{"class":34,"line":322},[32,923,64],{"emptyLinePlaceholder":63},[32,925,927],{"class":34,"line":926},29,[32,928,929],{"class":38},"    # Multiprocessing — TRUE parallelism (separate processes, separate GILs)\n",[32,931,933,935,937],{"class":34,"line":932},30,[32,934,768],{"class":74},[32,936,120],{"class":70},[32,938,824],{"class":74},[32,940,942,945,948,950,953,955],{"class":34,"line":941},31,[32,943,944],{"class":70},"    with",[32,946,947],{"class":74}," mp.Pool(",[32,949,865],{"class":102},[32,951,952],{"class":74},") ",[32,954,678],{"class":70},[32,956,957],{"class":74}," pool:\n",[32,959,961],{"class":34,"line":960},32,[32,962,963],{"class":74},"        pool.map(cpu_bound, [N, N])\n",[32,965,967,969,971,973,976,978,980,982,984,986,988,991],{"class":34,"line":966},33,[32,968,778],{"class":102},[32,970,263],{"class":74},[32,972,266],{"class":70},[32,974,975],{"class":269},"\"2 processes (CPU-bound): ",[32,977,273],{"class":102},[32,979,790],{"class":74},[32,981,793],{"class":70},[32,983,796],{"class":74},[32,985,799],{"class":70},[32,987,279],{"class":102},[32,989,990],{"class":269},"s  ← ~half\"",[32,992,295],{"class":74},[14,994,996],{"id":995},"production-environment-setup","Production Environment Setup",[19,998,1001],{"language":999,"filename":1000},"bash","setup.sh",[23,1002,1005],{"className":1003,"code":1004,"language":999,"meta":27,"style":27},"language-bash shiki shiki-themes github-light github-dark","# ── Production-grade Python environment bootstrap ──\n# Never use system Python for development — macOS ships 3.9 for OS tooling,\n# Ubuntu ships whatever the distro pinned. Both are stale and shared with OS tools.\n\n# Option A: uv (recommended 2025+) — manages interpreters AND venvs in one tool\ncurl -LsSf https:\u002F\u002Fastral.sh\u002Fuv\u002Finstall.sh | sh\neval \"$(uv generate-shell-support)\"   # or restart shell\n\nuv python install 3.12.4               # downloads + installs a standalone CPython\nuv python pin 3.12.4                    # writes .python-version for the project\nuv venv .venv                           # creates isolated venv with its own site-packages\nsource .venv\u002Fbin\u002Factivate\nuv pip install -e \".[dev]\"              # editable install + dev extras from pyproject.toml\n\n# Option B: pyenv + venv (traditional, works everywhere)\ncurl https:\u002F\u002Fpyenv.run | bash\nexport PYENV_ROOT=\"$HOME\u002F.pyenv\"\nexport PATH=\"$PYENV_ROOT\u002Fbin:$PATH\"\neval \"$(pyenv init -)\"\n\npyenv install 3.12.4\npyenv local 3.12.4                     # writes .python-version — pinned per-directory\npython -m venv .venv                   # stdlib venv: own interpreter + own site-packages\nsource .venv\u002Fbin\u002Factivate\npython -m pip install --upgrade pip    # bundled pip may lag by months\n",[29,1006,1007,1012,1017,1022,1026,1031,1048,1065,1069,1085,1099,1112,1120,1138,1142,1147,1159,1177,1200,1212,1216,1225,1237,1251,1257],{"__ignoreMap":27},[32,1008,1009],{"class":34,"line":35},[32,1010,1011],{"class":38},"# ── Production-grade Python environment bootstrap ──\n",[32,1013,1014],{"class":34,"line":42},[32,1015,1016],{"class":38},"# Never use system Python for development — macOS ships 3.9 for OS tooling,\n",[32,1018,1019],{"class":34,"line":48},[32,1020,1021],{"class":38},"# Ubuntu ships whatever the distro pinned. Both are stale and shared with OS tools.\n",[32,1023,1024],{"class":34,"line":54},[32,1025,64],{"emptyLinePlaceholder":63},[32,1027,1028],{"class":34,"line":60},[32,1029,1030],{"class":38},"# Option A: uv (recommended 2025+) — manages interpreters AND venvs in one tool\n",[32,1032,1033,1036,1039,1042,1045],{"class":34,"line":67},[32,1034,1035],{"class":95},"curl",[32,1037,1038],{"class":102}," -LsSf",[32,1040,1041],{"class":269}," https:\u002F\u002Fastral.sh\u002Fuv\u002Finstall.sh",[32,1043,1044],{"class":70}," |",[32,1046,1047],{"class":95}," sh\n",[32,1049,1050,1053,1056,1059,1062],{"class":34,"line":78},[32,1051,1052],{"class":102},"eval",[32,1054,1055],{"class":269}," \"$(",[32,1057,1058],{"class":95},"uv",[32,1060,1061],{"class":269}," generate-shell-support)\"",[32,1063,1064],{"class":38},"   # or restart shell\n",[32,1066,1067],{"class":34,"line":83},[32,1068,64],{"emptyLinePlaceholder":63},[32,1070,1071,1073,1076,1079,1082],{"class":34,"line":89},[32,1072,1058],{"class":95},[32,1074,1075],{"class":269}," python",[32,1077,1078],{"class":269}," install",[32,1080,1081],{"class":102}," 3.12.4",[32,1083,1084],{"class":38},"               # downloads + installs a standalone CPython\n",[32,1086,1087,1089,1091,1094,1096],{"class":34,"line":114},[32,1088,1058],{"class":95},[32,1090,1075],{"class":269},[32,1092,1093],{"class":269}," pin",[32,1095,1081],{"class":102},[32,1097,1098],{"class":38},"                    # writes .python-version for the project\n",[32,1100,1101,1103,1106,1109],{"class":34,"line":126},[32,1102,1058],{"class":95},[32,1104,1105],{"class":269}," venv",[32,1107,1108],{"class":269}," .venv",[32,1110,1111],{"class":38},"                           # creates isolated venv with its own site-packages\n",[32,1113,1114,1117],{"class":34,"line":141},[32,1115,1116],{"class":102},"source",[32,1118,1119],{"class":269}," .venv\u002Fbin\u002Factivate\n",[32,1121,1122,1124,1127,1129,1132,1135],{"class":34,"line":161},[32,1123,1058],{"class":95},[32,1125,1126],{"class":269}," pip",[32,1128,1078],{"class":269},[32,1130,1131],{"class":102}," -e",[32,1133,1134],{"class":269}," \".[dev]\"",[32,1136,1137],{"class":38},"              # editable install + dev extras from pyproject.toml\n",[32,1139,1140],{"class":34,"line":176},[32,1141,64],{"emptyLinePlaceholder":63},[32,1143,1144],{"class":34,"line":185},[32,1145,1146],{"class":38},"# Option B: pyenv + venv (traditional, works everywhere)\n",[32,1148,1149,1151,1154,1156],{"class":34,"line":190},[32,1150,1035],{"class":95},[32,1152,1153],{"class":269}," https:\u002F\u002Fpyenv.run",[32,1155,1044],{"class":70},[32,1157,1158],{"class":95}," bash\n",[32,1160,1161,1164,1167,1169,1171,1174],{"class":34,"line":196},[32,1162,1163],{"class":70},"export",[32,1165,1166],{"class":74}," PYENV_ROOT",[32,1168,120],{"class":70},[32,1170,292],{"class":269},[32,1172,1173],{"class":74},"$HOME",[32,1175,1176],{"class":269},"\u002F.pyenv\"\n",[32,1178,1179,1181,1184,1186,1188,1191,1194,1197],{"class":34,"line":202},[32,1180,1163],{"class":70},[32,1182,1183],{"class":74}," PATH",[32,1185,120],{"class":70},[32,1187,292],{"class":269},[32,1189,1190],{"class":74},"$PYENV_ROOT",[32,1192,1193],{"class":269},"\u002Fbin:",[32,1195,1196],{"class":74},"$PATH",[32,1198,1199],{"class":269},"\"\n",[32,1201,1202,1204,1206,1209],{"class":34,"line":208},[32,1203,1052],{"class":102},[32,1205,1055],{"class":269},[32,1207,1208],{"class":95},"pyenv",[32,1210,1211],{"class":269}," init -)\"\n",[32,1213,1214],{"class":34,"line":214},[32,1215,64],{"emptyLinePlaceholder":63},[32,1217,1218,1220,1222],{"class":34,"line":220},[32,1219,1208],{"class":95},[32,1221,1078],{"class":269},[32,1223,1224],{"class":102}," 3.12.4\n",[32,1226,1227,1229,1232,1234],{"class":34,"line":226},[32,1228,1208],{"class":95},[32,1230,1231],{"class":269}," local",[32,1233,1081],{"class":102},[32,1235,1236],{"class":38},"                     # writes .python-version — pinned per-directory\n",[32,1238,1239,1241,1244,1246,1248],{"class":34,"line":232},[32,1240,21],{"class":95},[32,1242,1243],{"class":102}," -m",[32,1245,1105],{"class":269},[32,1247,1108],{"class":269},[32,1249,1250],{"class":38},"                   # stdlib venv: own interpreter + own site-packages\n",[32,1252,1253,1255],{"class":34,"line":237},[32,1254,1116],{"class":102},[32,1256,1119],{"class":269},[32,1258,1259,1261,1263,1265,1267,1270,1272],{"class":34,"line":243},[32,1260,21],{"class":95},[32,1262,1243],{"class":102},[32,1264,1126],{"class":269},[32,1266,1078],{"class":269},[32,1268,1269],{"class":102}," --upgrade",[32,1271,1126],{"class":269},[32,1273,1274],{"class":38},"    # bundled pip may lag by months\n",[19,1276,1277],{"language":999},[23,1278,1280],{"className":1003,"code":1279,"language":999,"meta":27,"style":27},"# Verify the environment is correctly isolated — critical for debugging import issues\nwhich python                           # must resolve INSIDE .venv\u002Fbin\u002F, not system\npython -c \"import sys; print(sys.executable)\"  # the actual interpreter binary path\npython -c \"import sys; print(sys.prefix)\"       # venv root — differs from base_prefix\npython -c \"import sys; print(sys.path)\"        # site-packages should be .venv-local\npip show pip | grep Location            # confirms installs land in the right place\n",[29,1281,1282,1287,1297,1310,1322,1334],{"__ignoreMap":27},[32,1283,1284],{"class":34,"line":35},[32,1285,1286],{"class":38},"# Verify the environment is correctly isolated — critical for debugging import issues\n",[32,1288,1289,1292,1294],{"class":34,"line":42},[32,1290,1291],{"class":102},"which",[32,1293,1075],{"class":269},[32,1295,1296],{"class":38},"                           # must resolve INSIDE .venv\u002Fbin\u002F, not system\n",[32,1298,1299,1301,1304,1307],{"class":34,"line":48},[32,1300,21],{"class":95},[32,1302,1303],{"class":102}," -c",[32,1305,1306],{"class":269}," \"import sys; print(sys.executable)\"",[32,1308,1309],{"class":38},"  # the actual interpreter binary path\n",[32,1311,1312,1314,1316,1319],{"class":34,"line":54},[32,1313,21],{"class":95},[32,1315,1303],{"class":102},[32,1317,1318],{"class":269}," \"import sys; print(sys.prefix)\"",[32,1320,1321],{"class":38},"       # venv root — differs from base_prefix\n",[32,1323,1324,1326,1328,1331],{"class":34,"line":60},[32,1325,21],{"class":95},[32,1327,1303],{"class":102},[32,1329,1330],{"class":269}," \"import sys; print(sys.path)\"",[32,1332,1333],{"class":38},"        # site-packages should be .venv-local\n",[32,1335,1336,1339,1342,1344,1346,1349,1352],{"class":34,"line":67},[32,1337,1338],{"class":95},"pip",[32,1340,1341],{"class":269}," show",[32,1343,1126],{"class":269},[32,1345,1044],{"class":70},[32,1347,1348],{"class":95}," grep",[32,1350,1351],{"class":269}," Location",[32,1353,1354],{"class":38},"            # confirms installs land in the right place\n",[14,1356,1358],{"id":1357},"the-repl","The REPL",[1360,1361,1362,1363,1366],"p",{},"Python ships an interactive ",[575,1364,1365],{},"Read-Eval-Print Loop",". It's invaluable for exploring APIs, testing snippets, and debugging.",[19,1368,1369],{"language":999},[23,1370,1372],{"className":1003,"code":1371,"language":999,"meta":27,"style":27},"python\n",[29,1373,1374],{"__ignoreMap":27},[32,1375,1376],{"class":34,"line":35},[32,1377,1371],{"class":95},[19,1379,1380],{"language":21},[23,1381,1383],{"className":25,"code":1382,"language":21,"meta":27,"style":27},">>> 2 + 2\n4\n>>> import math\n>>> math.sqrt(16)\n4.0\n>>> name = \"Ada\"\n>>> f\"Hello, {name}!\"\n'Hello, Ada!'\n>>> exit()   # or Ctrl+D\n",[29,1384,1385,1399,1404,1414,1426,1431,1443,1463,1468],{"__ignoreMap":27},[32,1386,1387,1390,1393,1396],{"class":34,"line":35},[32,1388,1389],{"class":70},">>>",[32,1391,1392],{"class":102}," 2",[32,1394,1395],{"class":70}," +",[32,1397,1398],{"class":102}," 2\n",[32,1400,1401],{"class":34,"line":42},[32,1402,1403],{"class":102},"4\n",[32,1405,1406,1408,1411],{"class":34,"line":48},[32,1407,1389],{"class":70},[32,1409,1410],{"class":70}," import",[32,1412,1413],{"class":74}," math\n",[32,1415,1416,1418,1421,1424],{"class":34,"line":54},[32,1417,1389],{"class":70},[32,1419,1420],{"class":74}," math.sqrt(",[32,1422,1423],{"class":102},"16",[32,1425,295],{"class":74},[32,1427,1428],{"class":34,"line":60},[32,1429,1430],{"class":102},"4.0\n",[32,1432,1433,1435,1438,1440],{"class":34,"line":67},[32,1434,1389],{"class":70},[32,1436,1437],{"class":74}," name ",[32,1439,120],{"class":70},[32,1441,1442],{"class":269}," \"Ada\"\n",[32,1444,1445,1447,1450,1453,1455,1458,1460],{"class":34,"line":78},[32,1446,1389],{"class":70},[32,1448,1449],{"class":70}," f",[32,1451,1452],{"class":269},"\"Hello, ",[32,1454,273],{"class":102},[32,1456,1457],{"class":74},"name",[32,1459,279],{"class":102},[32,1461,1462],{"class":269},"!\"\n",[32,1464,1465],{"class":34,"line":83},[32,1466,1467],{"class":269},"'Hello, Ada!'\n",[32,1469,1470,1472,1475,1478],{"class":34,"line":89},[32,1471,1389],{"class":70},[32,1473,1474],{"class":102}," exit",[32,1476,1477],{"class":74},"()   ",[32,1479,1480],{"class":38},"# or Ctrl+D\n",[543,1482,1484],{"id":1483},"ipython-a-vastly-better-repl","IPython — a vastly better REPL",[1360,1486,1487,1488,1491],{},"The stock REPL is minimal. ",[29,1489,1490],{},"ipython"," adds syntax highlighting, tab completion, magic commands, and better tracebacks.",[19,1493,1494],{"language":999},[23,1495,1497],{"className":1003,"code":1496,"language":999,"meta":27,"style":27},"pip install ipython\nipython\n",[29,1498,1499,1508],{"__ignoreMap":27},[32,1500,1501,1503,1505],{"class":34,"line":35},[32,1502,1338],{"class":95},[32,1504,1078],{"class":269},[32,1506,1507],{"class":269}," ipython\n",[32,1509,1510],{"class":34,"line":42},[32,1511,1512],{"class":95},"ipython\n",[19,1514,1515],{"language":21},[23,1516,1518],{"className":25,"code":1517,"language":21,"meta":27,"style":27},"In [1]: %timeit sum(range(1000))\n6.53 µs ± 45.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n\nIn [2]: import requests   # tab-completion, ? for docs\nIn [3]: requests.get?     # shows docstring and signature\n",[29,1519,1520,1552,1578,1582,1598],{"__ignoreMap":27},[32,1521,1522,1525,1528,1531,1534,1537,1540,1542,1545,1547,1550],{"class":34,"line":35},[32,1523,1524],{"class":74},"In [",[32,1526,1527],{"class":102},"1",[32,1529,1530],{"class":74},"]: ",[32,1532,1533],{"class":70},"%",[32,1535,1536],{"class":74},"timeit ",[32,1538,1539],{"class":102},"sum",[32,1541,263],{"class":74},[32,1543,1544],{"class":102},"range",[32,1546,263],{"class":74},[32,1548,1549],{"class":102},"1000",[32,1551,536],{"class":74},[32,1553,1554,1557,1560,1563,1566,1569,1572,1575],{"class":34,"line":42},[32,1555,1556],{"class":102},"6.53",[32,1558,1559],{"class":74}," µs ± ",[32,1561,1562],{"class":102},"45.1",[32,1564,1565],{"class":74}," ns per loop (mean ± std. dev. of ",[32,1567,1568],{"class":102},"7",[32,1570,1571],{"class":74}," runs, ",[32,1573,1574],{"class":102},"100000",[32,1576,1577],{"class":74}," loops each)\n",[32,1579,1580],{"class":34,"line":48},[32,1581,64],{"emptyLinePlaceholder":63},[32,1583,1584,1586,1588,1590,1592,1595],{"class":34,"line":54},[32,1585,1524],{"class":74},[32,1587,865],{"class":102},[32,1589,1530],{"class":74},[32,1591,71],{"class":70},[32,1593,1594],{"class":74}," requests   ",[32,1596,1597],{"class":38},"# tab-completion, ? for docs\n",[32,1599,1600,1602,1605,1608,1612],{"class":34,"line":60},[32,1601,1524],{"class":74},[32,1603,1604],{"class":102},"3",[32,1606,1607],{"class":74},"]: requests.get",[32,1609,1611],{"class":1610},"sMKGj","?",[32,1613,1614],{"class":38},"     # shows docstring and signature\n",[14,1616,1618],{"id":1617},"running-scripts","Running Scripts",[19,1620,1622],{"language":21,"filename":1621},"hello.py",[23,1623,1625],{"className":25,"code":1624,"language":21,"meta":27,"style":27},"print(\"Hello, World!\")\n",[29,1626,1627],{"__ignoreMap":27},[32,1628,1629,1631,1633,1636],{"class":34,"line":35},[32,1630,260],{"class":102},[32,1632,263],{"class":74},[32,1634,1635],{"class":269},"\"Hello, World!\"",[32,1637,295],{"class":74},[19,1639,1640],{"language":999},[23,1641,1643],{"className":1003,"code":1642,"language":999,"meta":27,"style":27},"python hello.py\n# Hello, World!\n\n# Run as a module (adds the script's directory to sys.path differently —\n# matters for relative imports, see chapter 17)\npython -m hello\n\n# Pass arguments\npython hello.py arg1 arg2   # available via sys.argv\n",[29,1644,1645,1652,1657,1661,1666,1671,1680,1684,1689],{"__ignoreMap":27},[32,1646,1647,1649],{"class":34,"line":35},[32,1648,21],{"class":95},[32,1650,1651],{"class":269}," hello.py\n",[32,1653,1654],{"class":34,"line":42},[32,1655,1656],{"class":38},"# Hello, World!\n",[32,1658,1659],{"class":34,"line":48},[32,1660,64],{"emptyLinePlaceholder":63},[32,1662,1663],{"class":34,"line":54},[32,1664,1665],{"class":38},"# Run as a module (adds the script's directory to sys.path differently —\n",[32,1667,1668],{"class":34,"line":60},[32,1669,1670],{"class":38},"# matters for relative imports, see chapter 17)\n",[32,1672,1673,1675,1677],{"class":34,"line":67},[32,1674,21],{"class":95},[32,1676,1243],{"class":102},[32,1678,1679],{"class":269}," hello\n",[32,1681,1682],{"class":34,"line":78},[32,1683,64],{"emptyLinePlaceholder":63},[32,1685,1686],{"class":34,"line":83},[32,1687,1688],{"class":38},"# Pass arguments\n",[32,1690,1691,1693,1696,1699,1702],{"class":34,"line":89},[32,1692,21],{"class":95},[32,1694,1695],{"class":269}," hello.py",[32,1697,1698],{"class":269}," arg1",[32,1700,1701],{"class":269}," arg2",[32,1703,1704],{"class":38},"   # available via sys.argv\n",[543,1706,1708],{"id":1707},"the-shebang-line-and-executable-scripts","The shebang line and executable scripts",[19,1710,1712],{"language":21,"filename":1711},"greet.py",[23,1713,1715],{"className":25,"code":1714,"language":21,"meta":27,"style":27},"#!\u002Fusr\u002Fbin\u002Fenv python3\nprint(\"Hello from an executable script!\")\n",[29,1716,1717,1722],{"__ignoreMap":27},[32,1718,1719],{"class":34,"line":35},[32,1720,1721],{"class":38},"#!\u002Fusr\u002Fbin\u002Fenv python3\n",[32,1723,1724,1726,1728,1731],{"class":34,"line":42},[32,1725,260],{"class":102},[32,1727,263],{"class":74},[32,1729,1730],{"class":269},"\"Hello from an executable script!\"",[32,1732,295],{"class":74},[19,1734,1735],{"language":999},[23,1736,1738],{"className":1003,"code":1737,"language":999,"meta":27,"style":27},"chmod +x greet.py\n.\u002Fgreet.py\n",[29,1739,1740,1751],{"__ignoreMap":27},[32,1741,1742,1745,1748],{"class":34,"line":35},[32,1743,1744],{"class":95},"chmod",[32,1746,1747],{"class":269}," +x",[32,1749,1750],{"class":269}," greet.py\n",[32,1752,1753],{"class":34,"line":42},[32,1754,1755],{"class":95},".\u002Fgreet.py\n",[14,1757,1759,1762,1763,1766],{"id":1758},"py-vs-pyc-what-actually-happens-when-you-run-python",[29,1760,1761],{},".py"," vs ",[29,1764,1765],{},".pyc"," — What Actually Happens When You Run Python",[1360,1768,1769],{},"A common misconception is that Python is \"purely interpreted.\" In reality:",[1771,1772,1773,1788,1802],"ol",{},[1774,1775,1776,1777,1780,1781,1783,1784,1787],"li",{},"CPython ",[575,1778,1779],{},"compiles"," your ",[29,1782,1761],{}," source into ",[575,1785,1786],{},"bytecode"," (an intermediate, platform-independent instruction set for the CPython VM).",[1774,1789,1790,1791,1794,1795,1797,1798,1801],{},"That bytecode is cached in a ",[29,1792,1793],{},"__pycache__\u002F"," directory as ",[29,1796,1765],{}," files, named like ",[29,1799,1800],{},"module.cpython-312.pyc",", so re-running unchanged modules skips re-compilation.",[1774,1803,1804,1805,1808],{},"The ",[575,1806,1807],{},"CPython VM"," then interprets that bytecode — this step is the actual \"interpretation.\"",[19,1810,1811],{"language":999},[23,1812,1814],{"className":1003,"code":1813,"language":999,"meta":27,"style":27},"# Force-see the bytecode cache\npython -c \"import mymodule\"\nls __pycache__\u002F\n# mymodule.cpython-312.pyc\n\n# Inspect bytecode directly\npython -c \"\nimport dis\ndef add(a, b):\n    return a + b\ndis.dis(add)\n\"\n",[29,1815,1816,1821,1830,1838,1843,1847,1852,1861,1866,1871,1876,1881],{"__ignoreMap":27},[32,1817,1818],{"class":34,"line":35},[32,1819,1820],{"class":38},"# Force-see the bytecode cache\n",[32,1822,1823,1825,1827],{"class":34,"line":42},[32,1824,21],{"class":95},[32,1826,1303],{"class":102},[32,1828,1829],{"class":269}," \"import mymodule\"\n",[32,1831,1832,1835],{"class":34,"line":48},[32,1833,1834],{"class":95},"ls",[32,1836,1837],{"class":269}," __pycache__\u002F\n",[32,1839,1840],{"class":34,"line":54},[32,1841,1842],{"class":38},"# mymodule.cpython-312.pyc\n",[32,1844,1845],{"class":34,"line":60},[32,1846,64],{"emptyLinePlaceholder":63},[32,1848,1849],{"class":34,"line":67},[32,1850,1851],{"class":38},"# Inspect bytecode directly\n",[32,1853,1854,1856,1858],{"class":34,"line":78},[32,1855,21],{"class":95},[32,1857,1303],{"class":102},[32,1859,1860],{"class":269}," \"\n",[32,1862,1863],{"class":34,"line":83},[32,1864,1865],{"class":269},"import dis\n",[32,1867,1868],{"class":34,"line":89},[32,1869,1870],{"class":269},"def add(a, b):\n",[32,1872,1873],{"class":34,"line":114},[32,1874,1875],{"class":269},"    return a + b\n",[32,1877,1878],{"class":34,"line":126},[32,1879,1880],{"class":269},"dis.dis(add)\n",[32,1882,1883],{"class":34,"line":141},[32,1884,1199],{"class":269},[19,1886,1887],{"language":21},[23,1888,1890],{"className":25,"code":1889,"language":21,"meta":27,"style":27},"  2           0 RESUME                   0\n  3           2 LOAD_FAST                0 (a)\n              4 LOAD_FAST                1 (b)\n              6 BINARY_OP                0 (+)\n             10 RETURN_VALUE\n",[29,1891,1892,1906,1923,1936,1954],{"__ignoreMap":27},[32,1893,1894,1897,1900,1903],{"class":34,"line":35},[32,1895,1896],{"class":102},"  2",[32,1898,1899],{"class":102},"           0",[32,1901,1902],{"class":102}," RESUME",[32,1904,1905],{"class":102},"                   0\n",[32,1907,1908,1911,1914,1917,1920],{"class":34,"line":42},[32,1909,1910],{"class":102},"  3",[32,1912,1913],{"class":102},"           2",[32,1915,1916],{"class":102}," LOAD_FAST",[32,1918,1919],{"class":102},"                0",[32,1921,1922],{"class":74}," (a)\n",[32,1924,1925,1928,1930,1933],{"class":34,"line":48},[32,1926,1927],{"class":102},"              4",[32,1929,1916],{"class":102},[32,1931,1932],{"class":102},"                1",[32,1934,1935],{"class":74}," (b)\n",[32,1937,1938,1941,1944,1946,1949,1952],{"class":34,"line":54},[32,1939,1940],{"class":102},"              6",[32,1942,1943],{"class":102}," BINARY_OP",[32,1945,1919],{"class":102},[32,1947,1948],{"class":74}," (",[32,1950,1951],{"class":70},"+",[32,1953,295],{"class":74},[32,1955,1956,1959],{"class":34,"line":60},[32,1957,1958],{"class":102},"             10",[32,1960,1961],{"class":102}," RETURN_VALUE\n",[1360,1963,1964],{},"This matters because:",[1966,1967,1968,1978,1995],"ul",{},[1774,1969,1970,1972,1973,1977],{},[29,1971,1765],{}," caching is ",[1974,1975,1976],"em",{},"why"," the second run of an unchanged script\u002Fmodule import is faster than the first.",[1774,1979,1980,1982,1983,1986,1987,1990,1991,1994],{},[29,1981,1765],{}," files are ",[575,1984,1985],{},"not"," portable across major\u002Fminor Python versions or CPU architectures in a meaningful \"compiled binary\" sense — they're not a substitute for ahead-of-time compilation like C's ",[29,1988,1989],{},".o"," files. They only skip the ",[1974,1992,1993],{},"parse+compile"," step, not execution.",[1774,1996,1997,1998,2001,2002,2004,2005,2007,2008,2011,2012,2015],{},"Top-level script files (the one you invoke with ",[29,1999,2000],{},"python script.py",") are ",[575,2003,1985],{}," cached to ",[29,2006,1765],{}," — only ",[1974,2009,2010],{},"imported"," modules are. This is a frequent point of confusion when people expect ",[29,2013,2014],{},"__pycache__"," to appear next to their entry-point script.",[14,2017,2019],{"id":2018},"where-python-sits-in-the-compilation-spectrum","Where Python Sits in the Compilation Spectrum",[548,2021,2022,2038],{},[551,2023,2024],{},[554,2025,2026,2028,2031,2034,2036],{},[557,2027],{},[557,2029,2030],{},"C \u002F Rust",[557,2032,2033],{},"Java \u002F C#",[557,2035,577],{},[557,2037,590],{},[567,2039,2040,2057,2072],{},[554,2041,2042,2045,2048,2051,2054],{},[572,2043,2044],{},"Compiles to",[572,2046,2047],{},"Native code (AOT)",[572,2049,2050],{},"Bytecode → JIT to native",[572,2052,2053],{},"Bytecode (lazy, on import)",[572,2055,2056],{},"Bytecode → JIT (tracing)",[554,2058,2059,2062,2065,2067,2070],{},[572,2060,2061],{},"Type checking",[572,2063,2064],{},"Compile-time",[572,2066,2064],{},[572,2068,2069],{},"Runtime (dynamic)",[572,2071,2069],{},[554,2073,2074,2077,2080,2083,2086],{},[572,2075,2076],{},"CPU-bound loop speed",[572,2078,2079],{},"1× (baseline)",[572,2081,2082],{},"~0.8–1.2×",[572,2084,2085],{},"~30–100× slower",[572,2087,2088],{},"~3–10× slower",[19,2090,2091],{"language":21},[23,2092,2094],{"className":25,"code":2093,"language":21,"meta":27,"style":27},"# The performance gap, demonstrated — same algorithm, different execution paths\nimport time\n\nN = 5_000_000\n\n# Pure-Python loop — millions of bytecode dispatches, each with type dispatch overhead\nt0 = time.perf_counter()\ntotal = 0\nfor i in range(N):\n    total += i\npython_loop = time.perf_counter() - t0     # ~0.3s — each += is 4+ VM opcodes\n\n# Built-in sum() — single C function call, loop runs in compiled C, no per-element dispatch\nt0 = time.perf_counter()\ntotal = sum(range(N))                       # C-level iteration, no bytecode per element\nbuiltin_sum = time.perf_counter() - t0      # ~0.03s — 10× faster, same algorithm\n\n# numpy — SIMD-vectorized C, operates on contiguous memory blocks\nimport numpy as np\nt0 = time.perf_counter()\ntotal = int(np.arange(N).sum())              # single C call over a contiguous int64 buffer\nnumpy_sum = time.perf_counter() - t0         # ~0.005s — 60× faster than the Python loop\n\nprint(f\"python loop:  {python_loop:.4f}s  ({N:,} bytecode dispatches)\")\nprint(f\"builtin sum:  {builtin_sum:.4f}s  (1 C call)\")\nprint(f\"numpy sum:    {numpy_sum:.4f}s  (SIMD-vectorized C)\")\n",[29,2095,2096,2101,2108,2112,2122,2126,2131,2140,2149,2162,2171,2189,2193,2198,2206,2224,2241,2245,2250,2262,2270,2285,2302,2306,2345,2370],{"__ignoreMap":27},[32,2097,2098],{"class":34,"line":35},[32,2099,2100],{"class":38},"# The performance gap, demonstrated — same algorithm, different execution paths\n",[32,2102,2103,2105],{"class":34,"line":42},[32,2104,71],{"class":70},[32,2106,2107],{"class":74}," time\n",[32,2109,2110],{"class":34,"line":48},[32,2111,64],{"emptyLinePlaceholder":63},[32,2113,2114,2117,2119],{"class":34,"line":54},[32,2115,2116],{"class":74},"N ",[32,2118,120],{"class":70},[32,2120,2121],{"class":102}," 5_000_000\n",[32,2123,2124],{"class":34,"line":60},[32,2125,64],{"emptyLinePlaceholder":63},[32,2127,2128],{"class":34,"line":67},[32,2129,2130],{"class":38},"# Pure-Python loop — millions of bytecode dispatches, each with type dispatch overhead\n",[32,2132,2133,2136,2138],{"class":34,"line":78},[32,2134,2135],{"class":74},"t0 ",[32,2137,120],{"class":70},[32,2139,824],{"class":74},[32,2141,2142,2145,2147],{"class":34,"line":83},[32,2143,2144],{"class":74},"total ",[32,2146,120],{"class":70},[32,2148,123],{"class":102},[32,2150,2151,2153,2155,2157,2159],{"class":34,"line":89},[32,2152,714],{"class":70},[32,2154,711],{"class":74},[32,2156,135],{"class":70},[32,2158,721],{"class":102},[32,2160,2161],{"class":74},"(N):\n",[32,2163,2164,2166,2168],{"class":34,"line":114},[32,2165,117],{"class":74},[32,2167,167],{"class":70},[32,2169,2170],{"class":74}," i\n",[32,2172,2173,2176,2178,2181,2183,2186],{"class":34,"line":126},[32,2174,2175],{"class":74},"python_loop ",[32,2177,120],{"class":70},[32,2179,2180],{"class":74}," time.perf_counter() ",[32,2182,793],{"class":70},[32,2184,2185],{"class":74}," t0     ",[32,2187,2188],{"class":38},"# ~0.3s — each += is 4+ VM opcodes\n",[32,2190,2191],{"class":34,"line":141},[32,2192,64],{"emptyLinePlaceholder":63},[32,2194,2195],{"class":34,"line":161},[32,2196,2197],{"class":38},"# Built-in sum() — single C function call, loop runs in compiled C, no per-element dispatch\n",[32,2199,2200,2202,2204],{"class":34,"line":176},[32,2201,2135],{"class":74},[32,2203,120],{"class":70},[32,2205,824],{"class":74},[32,2207,2208,2210,2212,2214,2216,2218,2221],{"class":34,"line":185},[32,2209,2144],{"class":74},[32,2211,120],{"class":70},[32,2213,702],{"class":102},[32,2215,263],{"class":74},[32,2217,1544],{"class":102},[32,2219,2220],{"class":74},"(N))                       ",[32,2222,2223],{"class":38},"# C-level iteration, no bytecode per element\n",[32,2225,2226,2229,2231,2233,2235,2238],{"class":34,"line":190},[32,2227,2228],{"class":74},"builtin_sum ",[32,2230,120],{"class":70},[32,2232,2180],{"class":74},[32,2234,793],{"class":70},[32,2236,2237],{"class":74}," t0      ",[32,2239,2240],{"class":38},"# ~0.03s — 10× faster, same algorithm\n",[32,2242,2243],{"class":34,"line":196},[32,2244,64],{"emptyLinePlaceholder":63},[32,2246,2247],{"class":34,"line":202},[32,2248,2249],{"class":38},"# numpy — SIMD-vectorized C, operates on contiguous memory blocks\n",[32,2251,2252,2254,2257,2259],{"class":34,"line":208},[32,2253,71],{"class":70},[32,2255,2256],{"class":74}," numpy ",[32,2258,678],{"class":70},[32,2260,2261],{"class":74}," np\n",[32,2263,2264,2266,2268],{"class":34,"line":214},[32,2265,2135],{"class":74},[32,2267,120],{"class":70},[32,2269,824],{"class":74},[32,2271,2272,2274,2276,2279,2282],{"class":34,"line":220},[32,2273,2144],{"class":74},[32,2275,120],{"class":70},[32,2277,2278],{"class":102}," int",[32,2280,2281],{"class":74},"(np.arange(N).sum())              ",[32,2283,2284],{"class":38},"# single C call over a contiguous int64 buffer\n",[32,2286,2287,2290,2292,2294,2296,2299],{"class":34,"line":226},[32,2288,2289],{"class":74},"numpy_sum ",[32,2291,120],{"class":70},[32,2293,2180],{"class":74},[32,2295,793],{"class":70},[32,2297,2298],{"class":74}," t0         ",[32,2300,2301],{"class":38},"# ~0.005s — 60× faster than the Python loop\n",[32,2303,2304],{"class":34,"line":232},[32,2305,64],{"emptyLinePlaceholder":63},[32,2307,2308,2310,2312,2314,2317,2319,2322,2325,2327,2330,2332,2335,2338,2340,2343],{"class":34,"line":237},[32,2309,260],{"class":102},[32,2311,263],{"class":74},[32,2313,266],{"class":70},[32,2315,2316],{"class":269},"\"python loop:  ",[32,2318,273],{"class":102},[32,2320,2321],{"class":74},"python_loop",[32,2323,2324],{"class":70},":.4f",[32,2326,279],{"class":102},[32,2328,2329],{"class":269},"s  (",[32,2331,273],{"class":102},[32,2333,2334],{"class":74},"N",[32,2336,2337],{"class":70},":,",[32,2339,279],{"class":102},[32,2341,2342],{"class":269}," bytecode dispatches)\"",[32,2344,295],{"class":74},[32,2346,2347,2349,2351,2353,2356,2358,2361,2363,2365,2368],{"class":34,"line":243},[32,2348,260],{"class":102},[32,2350,263],{"class":74},[32,2352,266],{"class":70},[32,2354,2355],{"class":269},"\"builtin sum:  ",[32,2357,273],{"class":102},[32,2359,2360],{"class":74},"builtin_sum",[32,2362,2324],{"class":70},[32,2364,279],{"class":102},[32,2366,2367],{"class":269},"s  (1 C call)\"",[32,2369,295],{"class":74},[32,2371,2372,2374,2376,2378,2381,2383,2386,2388,2390,2393],{"class":34,"line":257},[32,2373,260],{"class":102},[32,2375,263],{"class":74},[32,2377,266],{"class":70},[32,2379,2380],{"class":269},"\"numpy sum:    ",[32,2382,273],{"class":102},[32,2384,2385],{"class":74},"numpy_sum",[32,2387,2324],{"class":70},[32,2389,279],{"class":102},[32,2391,2392],{"class":269},"s  (SIMD-vectorized C)\"",[32,2394,295],{"class":74},[14,2396,2398],{"id":2397},"project-structure-conventions","Project Structure Conventions",[19,2400,2401],{"language":999},[23,2402,2404],{"className":1003,"code":2403,"language":999,"meta":27,"style":27},"my-project\u002F\n├── pyproject.toml       # modern project metadata, deps, build config (ch. 25)\n├── README.md\n├── src\u002F\n│   └── my_project\u002F\n│       ├── __init__.py\n│       ├── main.py\n│       └── utils.py\n├── tests\u002F\n│   └── test_utils.py\n└── .python-version      # pyenv local version pin\n",[29,2405,2406,2411,2422,2429,2436,2447,2457,2466,2476,2483,2492],{"__ignoreMap":27},[32,2407,2408],{"class":34,"line":35},[32,2409,2410],{"class":95},"my-project\u002F\n",[32,2412,2413,2416,2419],{"class":34,"line":42},[32,2414,2415],{"class":95},"├──",[32,2417,2418],{"class":269}," pyproject.toml",[32,2420,2421],{"class":38},"       # modern project metadata, deps, build config (ch. 25)\n",[32,2423,2424,2426],{"class":34,"line":48},[32,2425,2415],{"class":95},[32,2427,2428],{"class":269}," README.md\n",[32,2430,2431,2433],{"class":34,"line":54},[32,2432,2415],{"class":95},[32,2434,2435],{"class":269}," src\u002F\n",[32,2437,2438,2441,2444],{"class":34,"line":60},[32,2439,2440],{"class":95},"│",[32,2442,2443],{"class":269},"   └──",[32,2445,2446],{"class":269}," my_project\u002F\n",[32,2448,2449,2451,2454],{"class":34,"line":67},[32,2450,2440],{"class":95},[32,2452,2453],{"class":269},"       ├──",[32,2455,2456],{"class":269}," __init__.py\n",[32,2458,2459,2461,2463],{"class":34,"line":78},[32,2460,2440],{"class":95},[32,2462,2453],{"class":269},[32,2464,2465],{"class":269}," main.py\n",[32,2467,2468,2470,2473],{"class":34,"line":83},[32,2469,2440],{"class":95},[32,2471,2472],{"class":269},"       └──",[32,2474,2475],{"class":269}," utils.py\n",[32,2477,2478,2480],{"class":34,"line":89},[32,2479,2415],{"class":95},[32,2481,2482],{"class":269}," tests\u002F\n",[32,2484,2485,2487,2489],{"class":34,"line":114},[32,2486,2440],{"class":95},[32,2488,2443],{"class":269},[32,2490,2491],{"class":269}," test_utils.py\n",[32,2493,2494,2497,2500],{"class":34,"line":126},[32,2495,2496],{"class":95},"└──",[32,2498,2499],{"class":269}," .python-version",[32,2501,2502],{"class":38},"      # pyenv local version pin\n",[14,2504,2506],{"id":2505},"tips-tricks","💡 Tips & Tricks",[1966,2508,2509,2521,2546,2569,2581],{},[1774,2510,2511,2516,2517,2520],{},[575,2512,2513],{},[29,2514,2515],{},"python -i script.py"," — Debug: runs the script, then drops you into a REPL with all its top-level names still bound, so you can poke at final state without adding ",[29,2518,2519],{},"breakpoint()"," calls.",[1774,2522,2523,2529,2530,2533,2534,2537,2538,2541,2542,2545],{},[575,2524,2525,2528],{},[29,2526,2527],{},"python -m"," runs installed tools as modules"," — ",[29,2531,2532],{},"python -m http.server 8000"," starts a static file server instantly; ",[29,2535,2536],{},"python -m venv .venv"," creates a virtual environment; ",[29,2539,2540],{},"python -m pip"," guarantees you're using the pip tied to ",[1974,2543,2544],{},"this"," interpreter, sidestepping PATH ambiguity between multiple Pythons.",[1774,2547,2548,2553,2554,2556,2557,2560,2561,2564,2565,2568],{},[575,2549,2550,2552],{},[29,2551,2519],{}," is the built-in debugger entry point"," — Since 3.7, calling ",[29,2555,2519],{}," anywhere in code drops into ",[29,2558,2559],{},"pdb"," (or whatever ",[29,2562,2563],{},"PYTHONBREAKPOINT"," points to) at that exact line — no ",[29,2566,2567],{},"import pdb; pdb.set_trace()"," boilerplate needed.",[1774,2570,2571,2529,2577,2580],{},[575,2572,2573,2576],{},[29,2574,2575],{},"python -c"," for one-liners",[29,2578,2579],{},"python -c \"import platform; print(platform.python_version())\""," runs code without creating a file; useful in shell scripts and CI checks.",[1774,2582,2583,2591],{},[575,2584,2585,2587,2588,2590],{},[29,2586,2014],{}," and ",[29,2589,1765],{}," files are safe to delete"," — They're purely a compile cache; deleting them just forces recompilation on next import, never a correctness issue (unless you're debugging a Python-version bytecode mismatch bug).",[14,2593,2595],{"id":2594},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[1966,2597,2598,2623,2641,2662,2680],{},[1774,2599,2600,2607,2608,2610,2611,2613,2614,2616,2617,2619,2620,2622],{},[575,2601,2602,1762,2604],{},[29,2603,21],{},[29,2605,2606],{},"python3"," — On many Linux distributions and older macOS versions, ",[29,2609,21],{}," either doesn't exist or still points to Python 2. Always use ",[29,2612,2606],{}," explicitly in portable scripts, or better, use ",[29,2615,1208],{},"\u002F",[29,2618,1058],{}," so ",[29,2621,21],{}," unambiguously resolves to your intended version.",[1774,2624,2625,2630,2631,2633,2634,2636,2637,2640],{},[575,2626,2627,2629],{},[29,2628,1765],{}," files can go stale across environments"," — If you copy a ",[29,2632,2014],{}," directory between machines running different Python patch versions, CPython detects the mismatch via an embedded magic number and simply recompiles — it does not silently run incompatible bytecode. Still, don't commit ",[29,2635,1793],{}," to version control; add it to ",[29,2638,2639],{},".gitignore",".",[1774,2642,2643,2529,2650,2653,2654,2657,2658,2661],{},[575,2644,2645,2646,2649],{},"The REPL's ",[29,2647,2648],{},"_"," holds the last expression's value",[29,2651,2652],{},">>> 2 + 2"," then ",[29,2655,2656],{},">>> _ * 10"," gives ",[29,2659,2660],{},"40",". This is genuinely useful but invisible unless you know it exists, and it only works for expressions typed directly at the prompt, not inside scripts.",[1774,2663,2664,2675,2676,2679],{},[575,2665,2666,2667,2670,2671,2674],{},"Indentation errors are ",[29,2668,2669],{},"IndentationError",", not ",[29,2672,2673],{},"SyntaxError",", and mixing tabs\u002Fspaces is a runtime error, not a style nit"," — Python 3 raises ",[29,2677,2678],{},"TabError: inconsistent use of tabs and spaces in indentation"," if a file mixes them in a way that's ambiguous, even if your editor renders it identically. Configure your editor to insert spaces only.",[1774,2681,2682,2694,2695,2698,2699,2702,2703,2706,2707,2710],{},[575,2683,2684,2686,2687,2690,2691],{},[29,2685,2000],{}," changes ",[29,2688,2689],{},"sys.path[0]"," differently than ",[29,2692,2693],{},"python -m package.module"," — Running a file directly inserts the ",[1974,2696,2697],{},"script's own directory"," at the front of ",[29,2700,2701],{},"sys.path","; running with ",[29,2704,2705],{},"-m"," inserts the ",[1974,2708,2709],{},"current working directory"," instead. This difference is the root cause of many \"it works when I run it one way but not the other\" import bugs — covered in depth in chapter 17.",[14,2712,2714],{"id":2713},"spot-the-bug","🧠 Spot the Bug",[1360,2716,2717,2718,2721],{},"A teammate says this script \"sometimes\" fails with ",[29,2719,2720],{},"ModuleNotFoundError"," depending on how they invoke it. Why?",[19,2723,2724],{"language":999},[23,2725,2727],{"className":1003,"code":2726,"language":999,"meta":27,"style":27},"# project layout:\n# project\u002F\n#   src\u002F\n#     app\u002F\n#       __init__.py\n#       main.py      # does `from app.utils import helper`\n#       utils.py\n\ncd project\u002Fsrc\u002Fapp\npython main.py\n",[29,2728,2729,2734,2739,2744,2749,2754,2759,2764,2768,2776],{"__ignoreMap":27},[32,2730,2731],{"class":34,"line":35},[32,2732,2733],{"class":38},"# project layout:\n",[32,2735,2736],{"class":34,"line":42},[32,2737,2738],{"class":38},"# project\u002F\n",[32,2740,2741],{"class":34,"line":48},[32,2742,2743],{"class":38},"#   src\u002F\n",[32,2745,2746],{"class":34,"line":54},[32,2747,2748],{"class":38},"#     app\u002F\n",[32,2750,2751],{"class":34,"line":60},[32,2752,2753],{"class":38},"#       __init__.py\n",[32,2755,2756],{"class":34,"line":67},[32,2757,2758],{"class":38},"#       main.py      # does `from app.utils import helper`\n",[32,2760,2761],{"class":34,"line":78},[32,2762,2763],{"class":38},"#       utils.py\n",[32,2765,2766],{"class":34,"line":83},[32,2767,64],{"emptyLinePlaceholder":63},[32,2769,2770,2773],{"class":34,"line":89},[32,2771,2772],{"class":102},"cd",[32,2774,2775],{"class":269}," project\u002Fsrc\u002Fapp\n",[32,2777,2778,2780],{"class":34,"line":114},[32,2779,21],{"class":95},[32,2781,2465],{"class":269},[2783,2784,2785,2789,2841],"details",{},[2786,2787,2788],"summary",{},"Answer",[1360,2790,2791,2792,2795,2796,2799,2800,2802,2803,2806,2807,2809,2810,2813,2814,2817,2818,2817,2821,2823,2824,2826,2827,2830,2831,2833,2834,2836,2837,2840],{},"Running ",[29,2793,2794],{},"python main.py"," from inside ",[29,2797,2798],{},"app\u002F"," puts ",[29,2801,2798],{}," itself (not ",[29,2804,2805],{},"src\u002F",") at the front of ",[29,2808,2701],{},". So ",[29,2811,2812],{},"from app.utils import helper"," fails — Python is looking for a package named ",[29,2815,2816],{},"app"," ",[1974,2819,2820],{},"inside",[29,2822,2798],{},", which doesn't exist. The fix is to run it as a module from the ",[29,2825,2805],{}," directory instead: ",[29,2828,2829],{},"cd project\u002Fsrc && python -m app.main",". This makes ",[29,2832,2805],{}," the path root, so ",[29,2835,2816],{}," resolves as the top-level package, and the internal ",[29,2838,2839],{},"app.utils"," import works correctly.",[1360,2842,2843,2846,2847,2849,2850,2852],{},[575,2844,2845],{},"The lesson",": how you invoke a script determines what ",[29,2848,2689],{}," is, which determines whether internal absolute imports succeed — always run package-internal entry points with ",[29,2851,2705],{}," from the project root, not as a bare script from inside the package.",[14,2854,2856],{"id":2855},"key-takeaways","Key Takeaways",[1966,2858,2859,2862,2871,2877,2880],{},[1774,2860,2861],{},"Python is dynamically typed, multi-paradigm, and reference-counted with a cycle-collecting GC; CPython is the reference implementation you should default to.",[1774,2863,2864,2865,2867,2868,2870],{},"Python source is compiled to bytecode (cached as ",[29,2866,1765],{}," in ",[29,2869,1793],{},") and then interpreted by the CPython VM — it is neither purely interpreted nor ahead-of-time compiled.",[1774,2872,2873,2874,2876],{},"Use ",[29,2875,1208],{}," to manage Python versions per-project instead of relying on the system Python.",[1774,2878,2879],{},"The REPL (or better, IPython) is a first-class tool for exploration, not just a toy.",[1774,2881,2882,2883,1762,2886,2889,2890,2892],{},"How you invoke a script (",[29,2884,2885],{},"python file.py",[29,2887,2888],{},"python -m pkg.module",") changes ",[29,2891,2701],{}," and can silently determine whether imports succeed.",[2894,2895,2896],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}html pre.shiki code .sMKGj, html code.shiki .sMKGj{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-github-dark:#FDAEB7;--shiki-github-dark-font-style:italic}",{"title":27,"searchDepth":42,"depth":42,"links":2898},[2899,2903,2904,2907,2910,2912,2913,2914,2915,2916,2917],{"id":16,"depth":42,"text":17,"children":2900},[2901,2902],{"id":545,"depth":48,"text":546},{"id":616,"depth":48,"text":617},{"id":995,"depth":42,"text":996},{"id":1357,"depth":42,"text":1358,"children":2905},[2906],{"id":1483,"depth":48,"text":1484},{"id":1617,"depth":42,"text":1618,"children":2908},[2909],{"id":1707,"depth":48,"text":1708},{"id":1758,"depth":42,"text":2911},".py vs .pyc — What Actually Happens When You Run Python",{"id":2018,"depth":42,"text":2019},{"id":2397,"depth":42,"text":2398},{"id":2505,"depth":42,"text":2506},{"id":2594,"depth":42,"text":2595},{"id":2713,"depth":42,"text":2714},{"id":2855,"depth":42,"text":2856},"md",{},"\u002Fpython\u002F01-introduction-and-setup",{"title":5,"description":27},"python\u002F01-introduction-and-setup","CG39jzxWgcstemRJqc9ieyigseB5fyLTCsxo_WA7icY",1789924651229]