[{"data":1,"prerenderedAt":3288},["ShallowReactive",2],{"page-\u002Fpython\u002F02-variables-and-data-types":3},{"id":4,"title":5,"body":6,"description":31,"extension":3282,"meta":3283,"navigation":60,"path":3284,"seo":3285,"stem":3286,"__hash__":3287},"content\u002Fpython\u002F02-variables-and-data-types.md","02 — Variables & Data Types",{"type":7,"value":8,"toc":3262},"minimark",[9,13,22,370,558,562,571,620,632,655,670,717,721,1359,1367,1500,1537,1547,1720,1745,1840,1844,1851,1957,1968,2049,2052,2056,2194,2200,2221,2264,2283,2393,2519,2523,2597,2695,2699,2790,2794,2959,2963,2966,3123,3206,3210,3258],[10,11,5],"h1",{"id":12},"_02-variables-data-types",[14,15,17,18],"h2",{"id":16},"the-object-model-every-value-is-a-heap-allocated-pyobject","The Object Model — Every Value Is a Heap-Allocated ",[19,20,21],"code",{},"PyObject",[23,24,26],"code-wrapper",{"language":25},"python",[27,28,32],"pre",{"className":29,"code":30,"language":25,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","# Every Python object starts with a C-level PyObject header:\n#   struct PyObject { Py_ssize_t ob_refcnt; PyTypeObject *ob_type; }\n# `id()` returns the address of this struct — that's why `is` is a pointer compare.\n\nimport sys, ctypes\n\n# ── Refcount introspection ──\n# Every object tracks how many names\u002Fcontainers reference it.\n# When refcnt hits 0, CPython IMMEDIATELY deallocates (no GC pause needed).\nobj = [1, 2, 3]\nprint(sys.getrefcount(obj))   # 2 — `obj` + the temporary arg passed to getrefcount\n\nalias = obj                    # refcnt → 3\nprint(sys.getrefcount(obj))   # 3\n\nimport weakref\nweak = weakref.ref(obj)       # weakref does NOT increment refcnt\nprint(sys.getrefcount(obj))   # still 3 — weak references don't keep objects alive\n\n# ── The cycle-collecting generational GC ──\n# Refcounting can't handle reference cycles. A separate 3-generation GC handles those.\nimport gc\ngc.disable()                  # pause GC to observe refcount-only behavior\n\na = {}; b = {}\na[\"link\"] = b                 # a → b: b.refcnt = 2 (b + a['link'])\nb[\"link\"] = a                 # b → a: a.refcnt = 2 (a + b['link'])\ndel a; del b                   # both refcnts are now 1 — they reference EACH OTHER but nothing references them\n                               # refcounting can't free them — only the cycle GC can\ngc.enable()\ncollected = gc.collect()       # manually triggers cycle detection — frees the orphaned cycle\nprint(f\"GC collected {collected} objects in cycles\")\n","",[19,33,34,43,49,55,62,73,78,84,90,96,126,138,143,157,167,172,180,194,204,209,215,221,229,238,243,259,280,298,315,321,327,341],{"__ignoreMap":31},[35,36,39],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"sdCPZ","# Every Python object starts with a C-level PyObject header:\n",[35,44,46],{"class":37,"line":45},2,[35,47,48],{"class":41},"#   struct PyObject { Py_ssize_t ob_refcnt; PyTypeObject *ob_type; }\n",[35,50,52],{"class":37,"line":51},3,[35,53,54],{"class":41},"# `id()` returns the address of this struct — that's why `is` is a pointer compare.\n",[35,56,58],{"class":37,"line":57},4,[35,59,61],{"emptyLinePlaceholder":60},true,"\n",[35,63,65,69],{"class":37,"line":64},5,[35,66,68],{"class":67},"svdQ7","import",[35,70,72],{"class":71},"ssxIu"," sys, ctypes\n",[35,74,76],{"class":37,"line":75},6,[35,77,61],{"emptyLinePlaceholder":60},[35,79,81],{"class":37,"line":80},7,[35,82,83],{"class":41},"# ── Refcount introspection ──\n",[35,85,87],{"class":37,"line":86},8,[35,88,89],{"class":41},"# Every object tracks how many names\u002Fcontainers reference it.\n",[35,91,93],{"class":37,"line":92},9,[35,94,95],{"class":41},"# When refcnt hits 0, CPython IMMEDIATELY deallocates (no GC pause needed).\n",[35,97,99,102,105,108,112,115,118,120,123],{"class":37,"line":98},10,[35,100,101],{"class":71},"obj ",[35,103,104],{"class":67},"=",[35,106,107],{"class":71}," [",[35,109,111],{"class":110},"snvgF","1",[35,113,114],{"class":71},", ",[35,116,117],{"class":110},"2",[35,119,114],{"class":71},[35,121,122],{"class":110},"3",[35,124,125],{"class":71},"]\n",[35,127,129,132,135],{"class":37,"line":128},11,[35,130,131],{"class":110},"print",[35,133,134],{"class":71},"(sys.getrefcount(obj))   ",[35,136,137],{"class":41},"# 2 — `obj` + the temporary arg passed to getrefcount\n",[35,139,141],{"class":37,"line":140},12,[35,142,61],{"emptyLinePlaceholder":60},[35,144,146,149,151,154],{"class":37,"line":145},13,[35,147,148],{"class":71},"alias ",[35,150,104],{"class":67},[35,152,153],{"class":71}," obj                    ",[35,155,156],{"class":41},"# refcnt → 3\n",[35,158,160,162,164],{"class":37,"line":159},14,[35,161,131],{"class":110},[35,163,134],{"class":71},[35,165,166],{"class":41},"# 3\n",[35,168,170],{"class":37,"line":169},15,[35,171,61],{"emptyLinePlaceholder":60},[35,173,175,177],{"class":37,"line":174},16,[35,176,68],{"class":67},[35,178,179],{"class":71}," weakref\n",[35,181,183,186,188,191],{"class":37,"line":182},17,[35,184,185],{"class":71},"weak ",[35,187,104],{"class":67},[35,189,190],{"class":71}," weakref.ref(obj)       ",[35,192,193],{"class":41},"# weakref does NOT increment refcnt\n",[35,195,197,199,201],{"class":37,"line":196},18,[35,198,131],{"class":110},[35,200,134],{"class":71},[35,202,203],{"class":41},"# still 3 — weak references don't keep objects alive\n",[35,205,207],{"class":37,"line":206},19,[35,208,61],{"emptyLinePlaceholder":60},[35,210,212],{"class":37,"line":211},20,[35,213,214],{"class":41},"# ── The cycle-collecting generational GC ──\n",[35,216,218],{"class":37,"line":217},21,[35,219,220],{"class":41},"# Refcounting can't handle reference cycles. A separate 3-generation GC handles those.\n",[35,222,224,226],{"class":37,"line":223},22,[35,225,68],{"class":67},[35,227,228],{"class":71}," gc\n",[35,230,232,235],{"class":37,"line":231},23,[35,233,234],{"class":71},"gc.disable()                  ",[35,236,237],{"class":41},"# pause GC to observe refcount-only behavior\n",[35,239,241],{"class":37,"line":240},24,[35,242,61],{"emptyLinePlaceholder":60},[35,244,246,249,251,254,256],{"class":37,"line":245},25,[35,247,248],{"class":71},"a ",[35,250,104],{"class":67},[35,252,253],{"class":71}," {}; b ",[35,255,104],{"class":67},[35,257,258],{"class":71}," {}\n",[35,260,262,265,269,272,274,277],{"class":37,"line":261},26,[35,263,264],{"class":71},"a[",[35,266,268],{"class":267},"sJ6F3","\"link\"",[35,270,271],{"class":71},"] ",[35,273,104],{"class":67},[35,275,276],{"class":71}," b                 ",[35,278,279],{"class":41},"# a → b: b.refcnt = 2 (b + a['link'])\n",[35,281,283,286,288,290,292,295],{"class":37,"line":282},27,[35,284,285],{"class":71},"b[",[35,287,268],{"class":267},[35,289,271],{"class":71},[35,291,104],{"class":67},[35,293,294],{"class":71}," a                 ",[35,296,297],{"class":41},"# b → a: a.refcnt = 2 (a + b['link'])\n",[35,299,301,304,307,309,312],{"class":37,"line":300},28,[35,302,303],{"class":67},"del",[35,305,306],{"class":71}," a; ",[35,308,303],{"class":67},[35,310,311],{"class":71}," b                   ",[35,313,314],{"class":41},"# both refcnts are now 1 — they reference EACH OTHER but nothing references them\n",[35,316,318],{"class":37,"line":317},29,[35,319,320],{"class":41},"                               # refcounting can't free them — only the cycle GC can\n",[35,322,324],{"class":37,"line":323},30,[35,325,326],{"class":71},"gc.enable()\n",[35,328,330,333,335,338],{"class":37,"line":329},31,[35,331,332],{"class":71},"collected ",[35,334,104],{"class":67},[35,336,337],{"class":71}," gc.collect()       ",[35,339,340],{"class":41},"# manually triggers cycle detection — frees the orphaned cycle\n",[35,342,344,346,349,352,355,358,361,364,367],{"class":37,"line":343},32,[35,345,131],{"class":110},[35,347,348],{"class":71},"(",[35,350,351],{"class":67},"f",[35,353,354],{"class":267},"\"GC collected ",[35,356,357],{"class":110},"{",[35,359,360],{"class":71},"collected",[35,362,363],{"class":110},"}",[35,365,366],{"class":267}," objects in cycles\"",[35,368,369],{"class":71},")\n",[23,371,372],{"language":25},[27,373,375],{"className":29,"code":374,"language":25,"meta":31,"style":31},"# ── Production: zero-copy data exchange via the buffer protocol ──\n# Different types (bytes, bytearray, array.array, numpy.ndarray, memoryview)\n# can share raw memory without copying — the buffer protocol exposes the C-level pointer.\n\nimport array, struct\n\n# Pack binary data into an array — contiguous C memory, not Python int objects\nbuf = array.array('I', [0xDEADBEEF, 0xCAFEBABE, 0x12345678])\nview = memoryview(buf)          # zero-copy view — no data copied, just a pointer + length\n\n# Cast the view to bytes to inspect raw memory layout (little-endian on x86)\nraw = view.cast('B')            # reinterpret as unsigned bytes\nprint(bytes(raw[:4]))           # b'\\xef\\xbe\\xad\\xde' — DEADBEEF in LE\n\n# Modify through the view — original buffer changes, no copy\nview[0] = 0xFFFFFFFF\nprint(buf[0])                   # 4294967295 — mutated through the view\n",[19,376,377,382,387,392,396,403,407,412,451,467,471,476,495,516,520,525,543],{"__ignoreMap":31},[35,378,379],{"class":37,"line":38},[35,380,381],{"class":41},"# ── Production: zero-copy data exchange via the buffer protocol ──\n",[35,383,384],{"class":37,"line":45},[35,385,386],{"class":41},"# Different types (bytes, bytearray, array.array, numpy.ndarray, memoryview)\n",[35,388,389],{"class":37,"line":51},[35,390,391],{"class":41},"# can share raw memory without copying — the buffer protocol exposes the C-level pointer.\n",[35,393,394],{"class":37,"line":57},[35,395,61],{"emptyLinePlaceholder":60},[35,397,398,400],{"class":37,"line":64},[35,399,68],{"class":67},[35,401,402],{"class":71}," array, struct\n",[35,404,405],{"class":37,"line":75},[35,406,61],{"emptyLinePlaceholder":60},[35,408,409],{"class":37,"line":80},[35,410,411],{"class":41},"# Pack binary data into an array — contiguous C memory, not Python int objects\n",[35,413,414,417,419,422,425,428,431,434,436,438,441,443,445,448],{"class":37,"line":86},[35,415,416],{"class":71},"buf ",[35,418,104],{"class":67},[35,420,421],{"class":71}," array.array(",[35,423,424],{"class":267},"'I'",[35,426,427],{"class":71},", [",[35,429,430],{"class":67},"0x",[35,432,433],{"class":110},"DEADBEEF",[35,435,114],{"class":71},[35,437,430],{"class":67},[35,439,440],{"class":110},"CAFEBABE",[35,442,114],{"class":71},[35,444,430],{"class":67},[35,446,447],{"class":110},"12345678",[35,449,450],{"class":71},"])\n",[35,452,453,456,458,461,464],{"class":37,"line":92},[35,454,455],{"class":71},"view ",[35,457,104],{"class":67},[35,459,460],{"class":110}," memoryview",[35,462,463],{"class":71},"(buf)          ",[35,465,466],{"class":41},"# zero-copy view — no data copied, just a pointer + length\n",[35,468,469],{"class":37,"line":98},[35,470,61],{"emptyLinePlaceholder":60},[35,472,473],{"class":37,"line":128},[35,474,475],{"class":41},"# Cast the view to bytes to inspect raw memory layout (little-endian on x86)\n",[35,477,478,481,483,486,489,492],{"class":37,"line":140},[35,479,480],{"class":71},"raw ",[35,482,104],{"class":67},[35,484,485],{"class":71}," view.cast(",[35,487,488],{"class":267},"'B'",[35,490,491],{"class":71},")            ",[35,493,494],{"class":41},"# reinterpret as unsigned bytes\n",[35,496,497,499,501,504,507,510,513],{"class":37,"line":145},[35,498,131],{"class":110},[35,500,348],{"class":71},[35,502,503],{"class":110},"bytes",[35,505,506],{"class":71},"(raw[:",[35,508,509],{"class":110},"4",[35,511,512],{"class":71},"]))           ",[35,514,515],{"class":41},"# b'\\xef\\xbe\\xad\\xde' — DEADBEEF in LE\n",[35,517,518],{"class":37,"line":159},[35,519,61],{"emptyLinePlaceholder":60},[35,521,522],{"class":37,"line":169},[35,523,524],{"class":41},"# Modify through the view — original buffer changes, no copy\n",[35,526,527,530,533,535,537,540],{"class":37,"line":174},[35,528,529],{"class":71},"view[",[35,531,532],{"class":110},"0",[35,534,271],{"class":71},[35,536,104],{"class":67},[35,538,539],{"class":67}," 0x",[35,541,542],{"class":110},"FFFFFFFF\n",[35,544,545,547,550,552,555],{"class":37,"line":182},[35,546,131],{"class":110},[35,548,549],{"class":71},"(buf[",[35,551,532],{"class":110},[35,553,554],{"class":71},"])                   ",[35,556,557],{"class":41},"# 4294967295 — mutated through the view\n",[14,559,561],{"id":560},"dynamic-typing","Dynamic Typing",[563,564,565,566,570],"p",{},"Types belong to ",[567,568,569],"strong",{},"objects",", not to the names bound to them. A name can be rebound to a value of any type at any time — there is no compile-time type declaration.",[23,572,573],{"language":25},[27,574,576],{"className":29,"code":575,"language":25,"meta":31,"style":31},"x = 42          # x refers to an int\nx = \"forty-two\" # now x refers to a str — perfectly legal\nx = [42]        # now a list\n",[19,577,578,591,603],{"__ignoreMap":31},[35,579,580,583,585,588],{"class":37,"line":38},[35,581,582],{"class":71},"x ",[35,584,104],{"class":67},[35,586,587],{"class":110}," 42",[35,589,590],{"class":41},"          # x refers to an int\n",[35,592,593,595,597,600],{"class":37,"line":45},[35,594,582],{"class":71},[35,596,104],{"class":67},[35,598,599],{"class":267}," \"forty-two\"",[35,601,602],{"class":41}," # now x refers to a str — perfectly legal\n",[35,604,605,607,609,611,614,617],{"class":37,"line":51},[35,606,582],{"class":71},[35,608,104],{"class":67},[35,610,107],{"class":71},[35,612,613],{"class":110},"42",[35,615,616],{"class":71},"]        ",[35,618,619],{"class":41},"# now a list\n",[563,621,622,623,627,628,631],{},"This is different from ",[624,625,626],"em",{},"weak"," typing. Python is dynamically ",[567,629,630],{},"but strongly"," typed — it will not silently coerce incompatible types.",[23,633,634],{"language":25},[27,635,637],{"className":29,"code":636,"language":25,"meta":31,"style":31},"\"3\" + 3\n# TypeError: can only concatenate str (not \"int\") to str\n",[19,638,639,650],{"__ignoreMap":31},[35,640,641,644,647],{"class":37,"line":38},[35,642,643],{"class":267},"\"3\"",[35,645,646],{"class":67}," +",[35,648,649],{"class":110}," 3\n",[35,651,652],{"class":37,"line":45},[35,653,654],{"class":41},"# TypeError: can only concatenate str (not \"int\") to str\n",[563,656,657,658,661,662,665,666,669],{},"Compare to JavaScript, which is dynamically and ",[624,659,660],{},"weakly"," typed: ",[19,663,664],{},"\"3\" + 3"," produces ",[19,667,668],{},"\"33\""," silently. Python demands you be explicit:",[23,671,672],{"language":25},[27,673,675],{"className":29,"code":674,"language":25,"meta":31,"style":31},"int(\"3\") + 3      # 6\n\"3\" + str(3)      # \"33\"\n",[19,676,677,698],{"__ignoreMap":31},[35,678,679,682,684,686,689,692,695],{"class":37,"line":38},[35,680,681],{"class":110},"int",[35,683,348],{"class":71},[35,685,643],{"class":267},[35,687,688],{"class":71},") ",[35,690,691],{"class":67},"+",[35,693,694],{"class":110}," 3",[35,696,697],{"class":41},"      # 6\n",[35,699,700,702,704,707,709,711,714],{"class":37,"line":45},[35,701,643],{"class":267},[35,703,646],{"class":67},[35,705,706],{"class":110}," str",[35,708,348],{"class":71},[35,710,122],{"class":110},[35,712,713],{"class":71},")      ",[35,715,716],{"class":41},"# \"33\"\n",[14,718,720],{"id":719},"scalar-type-internals-whats-actually-in-memory","Scalar Type Internals — What's Actually in Memory",[23,722,723],{"language":25},[27,724,726],{"className":29,"code":725,"language":25,"meta":31,"style":31},"import sys, struct, ctypes\n\n# ── int: arbitrary precision via digit arrays ──\n# Small ints (-5..256) are pre-allocated singletons — `is` accidentally works.\n# Large ints are PyLongObject with an array of 30-bit digits.\nprint(sys.getsizeof(0))           # 24 bytes — base PyObject overhead\nprint(sys.getsizeof(1))           # 28 bytes — one digit\nprint(sys.getsizeof(2**30))       # 32 bytes — one 30-bit digit\nprint(sys.getsizeof(2**60))       # 36 bytes — two 30-bit digits\nprint(sys.getsizeof(2**1000))     # 160 bytes — ~34 digits, no overflow ever\n\n# The small-int cache is observable — and is a CPython implementation detail, not a guarantee\na, b = 256, 256\nprint(a is b)                     # True — both resolve to the cached singleton\na, b = 257, 257\nprint(a is b)                     # False (usually) — separate allocations outside cache range\n# NEVER use `is` for value comparison — use `==`. `is` on ints is a latent bug.\n\n# ── float: IEEE-754 binary64, 8 bytes ──\n# Sign(1) + exponent(11) + mantissa(52) = 64 bits\nx = -0.0\npacked = struct.pack('>d', x)     # big-endian IEEE-754 bytes\nprint(packed.hex())               # 8000000000000000 — sign bit set, rest zero\nprint(x == 0.0)                   # True — -0.0 == 0.0 per IEEE-754\nprint(struct.pack('>d', 0.0).hex())  # 0000000000000000 — different bit pattern, same value\n\n# float('inf'), float('nan') are valid IEEE-754 special values\ninf = float('inf')\nprint(inf > 1e308)                # True\nprint(inf + 1 == inf)             # True — infinity absorbs addition\nnan = float('nan')\nprint(nan == nan)                 # False! NaN is never equal to itself — use math.isnan()\nprint(nan is nan)                 # True — same object, but == is False\n\n# ── bool: a subclass of int with singleton instances ──\n# True and False are the ONLY two bool instances. bool inherits ALL int operations.\nprint(isinstance(True, int))      # True — bool IS-A int in the type hierarchy\nprint(True + True + True)         # 3 — bool arithmetic produces int\nprint(sum([True, False, True]))   # 2 — bools are 1\u002F0 in numeric contexts\n\n# ANTI-PATTERN: using `isinstance(x, int)` to validate a \"count\" — bools pass!\ndef bad_count_validator(x):\n    if isinstance(x, int):\n        return x               # True\u002FFalse silently accepted as 1\u002F0\n    raise TypeError\n\n# CORRECT: exclude bool explicitly when the distinction matters\ndef good_count_validator(x):\n    if isinstance(x, int) and not isinstance(x, bool):\n        return x\n    raise TypeError(f\"expected int, got {type(x).__name__}\")\n",[19,727,728,735,739,744,749,754,769,782,802,820,839,843,848,863,879,893,906,911,915,920,925,937,956,966,985,1005,1009,1014,1031,1050,1070,1086,1101,1115,1120,1126,1132,1157,1181,1211,1216,1222,1235,1252,1264,1273,1278,1284,1294,1322,1330],{"__ignoreMap":31},[35,729,730,732],{"class":37,"line":38},[35,731,68],{"class":67},[35,733,734],{"class":71}," sys, struct, ctypes\n",[35,736,737],{"class":37,"line":45},[35,738,61],{"emptyLinePlaceholder":60},[35,740,741],{"class":37,"line":51},[35,742,743],{"class":41},"# ── int: arbitrary precision via digit arrays ──\n",[35,745,746],{"class":37,"line":57},[35,747,748],{"class":41},"# Small ints (-5..256) are pre-allocated singletons — `is` accidentally works.\n",[35,750,751],{"class":37,"line":64},[35,752,753],{"class":41},"# Large ints are PyLongObject with an array of 30-bit digits.\n",[35,755,756,758,761,763,766],{"class":37,"line":75},[35,757,131],{"class":110},[35,759,760],{"class":71},"(sys.getsizeof(",[35,762,532],{"class":110},[35,764,765],{"class":71},"))           ",[35,767,768],{"class":41},"# 24 bytes — base PyObject overhead\n",[35,770,771,773,775,777,779],{"class":37,"line":80},[35,772,131],{"class":110},[35,774,760],{"class":71},[35,776,111],{"class":110},[35,778,765],{"class":71},[35,780,781],{"class":41},"# 28 bytes — one digit\n",[35,783,784,786,788,790,793,796,799],{"class":37,"line":86},[35,785,131],{"class":110},[35,787,760],{"class":71},[35,789,117],{"class":110},[35,791,792],{"class":67},"**",[35,794,795],{"class":110},"30",[35,797,798],{"class":71},"))       ",[35,800,801],{"class":41},"# 32 bytes — one 30-bit digit\n",[35,803,804,806,808,810,812,815,817],{"class":37,"line":92},[35,805,131],{"class":110},[35,807,760],{"class":71},[35,809,117],{"class":110},[35,811,792],{"class":67},[35,813,814],{"class":110},"60",[35,816,798],{"class":71},[35,818,819],{"class":41},"# 36 bytes — two 30-bit digits\n",[35,821,822,824,826,828,830,833,836],{"class":37,"line":98},[35,823,131],{"class":110},[35,825,760],{"class":71},[35,827,117],{"class":110},[35,829,792],{"class":67},[35,831,832],{"class":110},"1000",[35,834,835],{"class":71},"))     ",[35,837,838],{"class":41},"# 160 bytes — ~34 digits, no overflow ever\n",[35,840,841],{"class":37,"line":128},[35,842,61],{"emptyLinePlaceholder":60},[35,844,845],{"class":37,"line":140},[35,846,847],{"class":41},"# The small-int cache is observable — and is a CPython implementation detail, not a guarantee\n",[35,849,850,853,855,858,860],{"class":37,"line":145},[35,851,852],{"class":71},"a, b ",[35,854,104],{"class":67},[35,856,857],{"class":110}," 256",[35,859,114],{"class":71},[35,861,862],{"class":110},"256\n",[35,864,865,867,870,873,876],{"class":37,"line":159},[35,866,131],{"class":110},[35,868,869],{"class":71},"(a ",[35,871,872],{"class":67},"is",[35,874,875],{"class":71}," b)                     ",[35,877,878],{"class":41},"# True — both resolve to the cached singleton\n",[35,880,881,883,885,888,890],{"class":37,"line":169},[35,882,852],{"class":71},[35,884,104],{"class":67},[35,886,887],{"class":110}," 257",[35,889,114],{"class":71},[35,891,892],{"class":110},"257\n",[35,894,895,897,899,901,903],{"class":37,"line":174},[35,896,131],{"class":110},[35,898,869],{"class":71},[35,900,872],{"class":67},[35,902,875],{"class":71},[35,904,905],{"class":41},"# False (usually) — separate allocations outside cache range\n",[35,907,908],{"class":37,"line":182},[35,909,910],{"class":41},"# NEVER use `is` for value comparison — use `==`. `is` on ints is a latent bug.\n",[35,912,913],{"class":37,"line":196},[35,914,61],{"emptyLinePlaceholder":60},[35,916,917],{"class":37,"line":206},[35,918,919],{"class":41},"# ── float: IEEE-754 binary64, 8 bytes ──\n",[35,921,922],{"class":37,"line":211},[35,923,924],{"class":41},"# Sign(1) + exponent(11) + mantissa(52) = 64 bits\n",[35,926,927,929,931,934],{"class":37,"line":217},[35,928,582],{"class":71},[35,930,104],{"class":67},[35,932,933],{"class":67}," -",[35,935,936],{"class":110},"0.0\n",[35,938,939,942,944,947,950,953],{"class":37,"line":223},[35,940,941],{"class":71},"packed ",[35,943,104],{"class":67},[35,945,946],{"class":71}," struct.pack(",[35,948,949],{"class":267},"'>d'",[35,951,952],{"class":71},", x)     ",[35,954,955],{"class":41},"# big-endian IEEE-754 bytes\n",[35,957,958,960,963],{"class":37,"line":231},[35,959,131],{"class":110},[35,961,962],{"class":71},"(packed.hex())               ",[35,964,965],{"class":41},"# 8000000000000000 — sign bit set, rest zero\n",[35,967,968,970,973,976,979,982],{"class":37,"line":240},[35,969,131],{"class":110},[35,971,972],{"class":71},"(x ",[35,974,975],{"class":67},"==",[35,977,978],{"class":110}," 0.0",[35,980,981],{"class":71},")                   ",[35,983,984],{"class":41},"# True — -0.0 == 0.0 per IEEE-754\n",[35,986,987,989,992,994,996,999,1002],{"class":37,"line":245},[35,988,131],{"class":110},[35,990,991],{"class":71},"(struct.pack(",[35,993,949],{"class":267},[35,995,114],{"class":71},[35,997,998],{"class":110},"0.0",[35,1000,1001],{"class":71},").hex())  ",[35,1003,1004],{"class":41},"# 0000000000000000 — different bit pattern, same value\n",[35,1006,1007],{"class":37,"line":261},[35,1008,61],{"emptyLinePlaceholder":60},[35,1010,1011],{"class":37,"line":282},[35,1012,1013],{"class":41},"# float('inf'), float('nan') are valid IEEE-754 special values\n",[35,1015,1016,1019,1021,1024,1026,1029],{"class":37,"line":300},[35,1017,1018],{"class":71},"inf ",[35,1020,104],{"class":67},[35,1022,1023],{"class":110}," float",[35,1025,348],{"class":71},[35,1027,1028],{"class":267},"'inf'",[35,1030,369],{"class":71},[35,1032,1033,1035,1038,1041,1044,1047],{"class":37,"line":317},[35,1034,131],{"class":110},[35,1036,1037],{"class":71},"(inf ",[35,1039,1040],{"class":67},">",[35,1042,1043],{"class":110}," 1e308",[35,1045,1046],{"class":71},")                ",[35,1048,1049],{"class":41},"# True\n",[35,1051,1052,1054,1056,1058,1061,1064,1067],{"class":37,"line":323},[35,1053,131],{"class":110},[35,1055,1037],{"class":71},[35,1057,691],{"class":67},[35,1059,1060],{"class":110}," 1",[35,1062,1063],{"class":67}," ==",[35,1065,1066],{"class":71}," inf)             ",[35,1068,1069],{"class":41},"# True — infinity absorbs addition\n",[35,1071,1072,1075,1077,1079,1081,1084],{"class":37,"line":329},[35,1073,1074],{"class":71},"nan ",[35,1076,104],{"class":67},[35,1078,1023],{"class":110},[35,1080,348],{"class":71},[35,1082,1083],{"class":267},"'nan'",[35,1085,369],{"class":71},[35,1087,1088,1090,1093,1095,1098],{"class":37,"line":343},[35,1089,131],{"class":110},[35,1091,1092],{"class":71},"(nan ",[35,1094,975],{"class":67},[35,1096,1097],{"class":71}," nan)                 ",[35,1099,1100],{"class":41},"# False! NaN is never equal to itself — use math.isnan()\n",[35,1102,1104,1106,1108,1110,1112],{"class":37,"line":1103},33,[35,1105,131],{"class":110},[35,1107,1092],{"class":71},[35,1109,872],{"class":67},[35,1111,1097],{"class":71},[35,1113,1114],{"class":41},"# True — same object, but == is False\n",[35,1116,1118],{"class":37,"line":1117},34,[35,1119,61],{"emptyLinePlaceholder":60},[35,1121,1123],{"class":37,"line":1122},35,[35,1124,1125],{"class":41},"# ── bool: a subclass of int with singleton instances ──\n",[35,1127,1129],{"class":37,"line":1128},36,[35,1130,1131],{"class":41},"# True and False are the ONLY two bool instances. bool inherits ALL int operations.\n",[35,1133,1135,1137,1139,1142,1144,1147,1149,1151,1154],{"class":37,"line":1134},37,[35,1136,131],{"class":110},[35,1138,348],{"class":71},[35,1140,1141],{"class":110},"isinstance",[35,1143,348],{"class":71},[35,1145,1146],{"class":110},"True",[35,1148,114],{"class":71},[35,1150,681],{"class":110},[35,1152,1153],{"class":71},"))      ",[35,1155,1156],{"class":41},"# True — bool IS-A int in the type hierarchy\n",[35,1158,1160,1162,1164,1166,1168,1171,1173,1175,1178],{"class":37,"line":1159},38,[35,1161,131],{"class":110},[35,1163,348],{"class":71},[35,1165,1146],{"class":110},[35,1167,646],{"class":67},[35,1169,1170],{"class":110}," True",[35,1172,646],{"class":67},[35,1174,1170],{"class":110},[35,1176,1177],{"class":71},")         ",[35,1179,1180],{"class":41},"# 3 — bool arithmetic produces int\n",[35,1182,1184,1186,1188,1191,1194,1196,1198,1201,1203,1205,1208],{"class":37,"line":1183},39,[35,1185,131],{"class":110},[35,1187,348],{"class":71},[35,1189,1190],{"class":110},"sum",[35,1192,1193],{"class":71},"([",[35,1195,1146],{"class":110},[35,1197,114],{"class":71},[35,1199,1200],{"class":110},"False",[35,1202,114],{"class":71},[35,1204,1146],{"class":110},[35,1206,1207],{"class":71},"]))   ",[35,1209,1210],{"class":41},"# 2 — bools are 1\u002F0 in numeric contexts\n",[35,1212,1214],{"class":37,"line":1213},40,[35,1215,61],{"emptyLinePlaceholder":60},[35,1217,1219],{"class":37,"line":1218},41,[35,1220,1221],{"class":41},"# ANTI-PATTERN: using `isinstance(x, int)` to validate a \"count\" — bools pass!\n",[35,1223,1225,1228,1232],{"class":37,"line":1224},42,[35,1226,1227],{"class":67},"def",[35,1229,1231],{"class":1230},"sIsaT"," bad_count_validator",[35,1233,1234],{"class":71},"(x):\n",[35,1236,1238,1241,1244,1247,1249],{"class":37,"line":1237},43,[35,1239,1240],{"class":67},"    if",[35,1242,1243],{"class":110}," isinstance",[35,1245,1246],{"class":71},"(x, ",[35,1248,681],{"class":110},[35,1250,1251],{"class":71},"):\n",[35,1253,1255,1258,1261],{"class":37,"line":1254},44,[35,1256,1257],{"class":67},"        return",[35,1259,1260],{"class":71}," x               ",[35,1262,1263],{"class":41},"# True\u002FFalse silently accepted as 1\u002F0\n",[35,1265,1267,1270],{"class":37,"line":1266},45,[35,1268,1269],{"class":67},"    raise",[35,1271,1272],{"class":110}," TypeError\n",[35,1274,1276],{"class":37,"line":1275},46,[35,1277,61],{"emptyLinePlaceholder":60},[35,1279,1281],{"class":37,"line":1280},47,[35,1282,1283],{"class":41},"# CORRECT: exclude bool explicitly when the distinction matters\n",[35,1285,1287,1289,1292],{"class":37,"line":1286},48,[35,1288,1227],{"class":67},[35,1290,1291],{"class":1230}," good_count_validator",[35,1293,1234],{"class":71},[35,1295,1297,1299,1301,1303,1305,1307,1310,1313,1315,1317,1320],{"class":37,"line":1296},49,[35,1298,1240],{"class":67},[35,1300,1243],{"class":110},[35,1302,1246],{"class":71},[35,1304,681],{"class":110},[35,1306,688],{"class":71},[35,1308,1309],{"class":67},"and",[35,1311,1312],{"class":67}," not",[35,1314,1243],{"class":110},[35,1316,1246],{"class":71},[35,1318,1319],{"class":110},"bool",[35,1321,1251],{"class":71},[35,1323,1325,1327],{"class":37,"line":1324},50,[35,1326,1257],{"class":67},[35,1328,1329],{"class":71}," x\n",[35,1331,1333,1335,1338,1340,1342,1345,1348,1351,1354,1357],{"class":37,"line":1332},51,[35,1334,1269],{"class":67},[35,1336,1337],{"class":110}," TypeError",[35,1339,348],{"class":71},[35,1341,351],{"class":67},[35,1343,1344],{"class":267},"\"expected int, got ",[35,1346,1347],{"class":110},"{type",[35,1349,1350],{"class":71},"(x).",[35,1352,1353],{"class":110},"__name__}",[35,1355,1356],{"class":267},"\"",[35,1358,369],{"class":71},[1360,1361,1363,1366],"h3",{"id":1362},"none-is-not-falsy-zero-its-a-distinct-singleton",[19,1364,1365],{},"None"," is not \"falsy zero\" — it's a distinct singleton",[23,1368,1369],{"language":25},[27,1370,1372],{"className":29,"code":1371,"language":25,"meta":31,"style":31},"def get_config(key):\n    config = {\"debug\": False, \"timeout\": 0}\n    return config.get(key)  # returns None if key is absent\n\nvalue = get_config(\"missing_key\")\nif value == 0:\n    print(\"This never runs — None != 0\")\nif value is None:\n    print(\"Correct check\")   # this runs\n",[19,1373,1374,1384,1414,1425,1429,1444,1460,1472,1485],{"__ignoreMap":31},[35,1375,1376,1378,1381],{"class":37,"line":38},[35,1377,1227],{"class":67},[35,1379,1380],{"class":1230}," get_config",[35,1382,1383],{"class":71},"(key):\n",[35,1385,1386,1389,1391,1394,1397,1400,1402,1404,1407,1409,1411],{"class":37,"line":45},[35,1387,1388],{"class":71},"    config ",[35,1390,104],{"class":67},[35,1392,1393],{"class":71}," {",[35,1395,1396],{"class":267},"\"debug\"",[35,1398,1399],{"class":71},": ",[35,1401,1200],{"class":110},[35,1403,114],{"class":71},[35,1405,1406],{"class":267},"\"timeout\"",[35,1408,1399],{"class":71},[35,1410,532],{"class":110},[35,1412,1413],{"class":71},"}\n",[35,1415,1416,1419,1422],{"class":37,"line":51},[35,1417,1418],{"class":67},"    return",[35,1420,1421],{"class":71}," config.get(key)  ",[35,1423,1424],{"class":41},"# returns None if key is absent\n",[35,1426,1427],{"class":37,"line":57},[35,1428,61],{"emptyLinePlaceholder":60},[35,1430,1431,1434,1436,1439,1442],{"class":37,"line":64},[35,1432,1433],{"class":71},"value ",[35,1435,104],{"class":67},[35,1437,1438],{"class":71}," get_config(",[35,1440,1441],{"class":267},"\"missing_key\"",[35,1443,369],{"class":71},[35,1445,1446,1449,1452,1454,1457],{"class":37,"line":75},[35,1447,1448],{"class":67},"if",[35,1450,1451],{"class":71}," value ",[35,1453,975],{"class":67},[35,1455,1456],{"class":110}," 0",[35,1458,1459],{"class":71},":\n",[35,1461,1462,1465,1467,1470],{"class":37,"line":80},[35,1463,1464],{"class":110},"    print",[35,1466,348],{"class":71},[35,1468,1469],{"class":267},"\"This never runs — None != 0\"",[35,1471,369],{"class":71},[35,1473,1474,1476,1478,1480,1483],{"class":37,"line":86},[35,1475,1448],{"class":67},[35,1477,1451],{"class":71},[35,1479,872],{"class":67},[35,1481,1482],{"class":110}," None",[35,1484,1459],{"class":71},[35,1486,1487,1489,1491,1494,1497],{"class":37,"line":92},[35,1488,1464],{"class":110},[35,1490,348],{"class":71},[35,1492,1493],{"class":267},"\"Correct check\"",[35,1495,1496],{"class":71},")   ",[35,1498,1499],{"class":41},"# this runs\n",[563,1501,1502,1503,1505,1506,1508,1509,1512,1513,1515,1516,1518,1519,1522,1523,1525,1526,1508,1529,1532,1533,1536],{},"Always compare ",[19,1504,1365],{}," with ",[19,1507,872],{},"\u002F",[19,1510,1511],{},"is not",", never ",[19,1514,975],{},". ",[19,1517,1365],{}," is a ",[567,1520,1521],{},"singleton"," — there is only ever one ",[19,1524,1365],{}," object in a running process, so identity comparison is both correct and idiomatic (enforced by linters like ",[19,1527,1528],{},"ruff",[19,1530,1531],{},"flake8"," via ",[19,1534,1535],{},"E711",").",[14,1538,1540,1543,1544],{"id":1539},"type-vs-isinstance",[19,1541,1542],{},"type()"," vs ",[19,1545,1546],{},"isinstance()",[23,1548,1549],{"language":25},[27,1550,1552],{"className":29,"code":1551,"language":25,"meta":31,"style":31},"class Animal:\n    pass\n\nclass Dog(Animal):\n    pass\n\nd = Dog()\n\nprint(type(d) == Dog)          # True\nprint(type(d) == Animal)       # False — type() is exact, no inheritance awareness\nprint(isinstance(d, Animal))   # True — isinstance() respects the class hierarchy\nprint(isinstance(d, Dog))      # True\nprint(isinstance(True, int))   # True — bool IS-A int\nprint(type(True) == int)       # False — exact type is bool, not int\n",[19,1553,1554,1564,1569,1573,1587,1591,1595,1605,1609,1628,1646,1660,1673,1695],{"__ignoreMap":31},[35,1555,1556,1559,1562],{"class":37,"line":38},[35,1557,1558],{"class":67},"class",[35,1560,1561],{"class":1230}," Animal",[35,1563,1459],{"class":71},[35,1565,1566],{"class":37,"line":45},[35,1567,1568],{"class":67},"    pass\n",[35,1570,1571],{"class":37,"line":51},[35,1572,61],{"emptyLinePlaceholder":60},[35,1574,1575,1577,1580,1582,1585],{"class":37,"line":57},[35,1576,1558],{"class":67},[35,1578,1579],{"class":1230}," Dog",[35,1581,348],{"class":71},[35,1583,1584],{"class":1230},"Animal",[35,1586,1251],{"class":71},[35,1588,1589],{"class":37,"line":64},[35,1590,1568],{"class":67},[35,1592,1593],{"class":37,"line":75},[35,1594,61],{"emptyLinePlaceholder":60},[35,1596,1597,1600,1602],{"class":37,"line":80},[35,1598,1599],{"class":71},"d ",[35,1601,104],{"class":67},[35,1603,1604],{"class":71}," Dog()\n",[35,1606,1607],{"class":37,"line":86},[35,1608,61],{"emptyLinePlaceholder":60},[35,1610,1611,1613,1615,1618,1621,1623,1626],{"class":37,"line":92},[35,1612,131],{"class":110},[35,1614,348],{"class":71},[35,1616,1617],{"class":110},"type",[35,1619,1620],{"class":71},"(d) ",[35,1622,975],{"class":67},[35,1624,1625],{"class":71}," Dog)          ",[35,1627,1049],{"class":41},[35,1629,1630,1632,1634,1636,1638,1640,1643],{"class":37,"line":98},[35,1631,131],{"class":110},[35,1633,348],{"class":71},[35,1635,1617],{"class":110},[35,1637,1620],{"class":71},[35,1639,975],{"class":67},[35,1641,1642],{"class":71}," Animal)       ",[35,1644,1645],{"class":41},"# False — type() is exact, no inheritance awareness\n",[35,1647,1648,1650,1652,1654,1657],{"class":37,"line":128},[35,1649,131],{"class":110},[35,1651,348],{"class":71},[35,1653,1141],{"class":110},[35,1655,1656],{"class":71},"(d, Animal))   ",[35,1658,1659],{"class":41},"# True — isinstance() respects the class hierarchy\n",[35,1661,1662,1664,1666,1668,1671],{"class":37,"line":140},[35,1663,131],{"class":110},[35,1665,348],{"class":71},[35,1667,1141],{"class":110},[35,1669,1670],{"class":71},"(d, Dog))      ",[35,1672,1049],{"class":41},[35,1674,1675,1677,1679,1681,1683,1685,1687,1689,1692],{"class":37,"line":145},[35,1676,131],{"class":110},[35,1678,348],{"class":71},[35,1680,1141],{"class":110},[35,1682,348],{"class":71},[35,1684,1146],{"class":110},[35,1686,114],{"class":71},[35,1688,681],{"class":110},[35,1690,1691],{"class":71},"))   ",[35,1693,1694],{"class":41},"# True — bool IS-A int\n",[35,1696,1697,1699,1701,1703,1705,1707,1709,1711,1714,1717],{"class":37,"line":159},[35,1698,131],{"class":110},[35,1700,348],{"class":71},[35,1702,1617],{"class":110},[35,1704,348],{"class":71},[35,1706,1146],{"class":110},[35,1708,688],{"class":71},[35,1710,975],{"class":67},[35,1712,1713],{"class":110}," int",[35,1715,1716],{"class":71},")       ",[35,1718,1719],{"class":41},"# False — exact type is bool, not int\n",[563,1721,1722,1725,1726,1728,1729,1732,1733,1736,1737,1740,1741,1744],{},[567,1723,1724],{},"Best practice",": use ",[19,1727,1546],{}," for type checks in almost all real code — it correctly handles inheritance and is the only option that works with ",[19,1730,1731],{},"Protocol","\u002FABC-based duck typing (chapter 20). Reserve ",[19,1734,1735],{},"type(x) == Y"," for the rare case where you deliberately want to ",[624,1738,1739],{},"exclude"," subclasses (e.g., security-sensitive ",[19,1742,1743],{},"pickle"," deserialization checks, chapter 27).",[23,1746,1747],{"language":25},[27,1748,1750],{"className":29,"code":1749,"language":25,"meta":31,"style":31},"# isinstance also accepts a tuple of types\ndef normalize(value):\n    if isinstance(value, (int, float)):\n        return float(value)\n    if isinstance(value, str):\n        return value.strip().lower()\n    raise TypeError(f\"Unsupported type: {type(value).__name__}\")\n",[19,1751,1752,1757,1767,1786,1795,1809,1816],{"__ignoreMap":31},[35,1753,1754],{"class":37,"line":38},[35,1755,1756],{"class":41},"# isinstance also accepts a tuple of types\n",[35,1758,1759,1761,1764],{"class":37,"line":45},[35,1760,1227],{"class":67},[35,1762,1763],{"class":1230}," normalize",[35,1765,1766],{"class":71},"(value):\n",[35,1768,1769,1771,1773,1776,1778,1780,1783],{"class":37,"line":51},[35,1770,1240],{"class":67},[35,1772,1243],{"class":110},[35,1774,1775],{"class":71},"(value, (",[35,1777,681],{"class":110},[35,1779,114],{"class":71},[35,1781,1782],{"class":110},"float",[35,1784,1785],{"class":71},")):\n",[35,1787,1788,1790,1792],{"class":37,"line":57},[35,1789,1257],{"class":67},[35,1791,1023],{"class":110},[35,1793,1794],{"class":71},"(value)\n",[35,1796,1797,1799,1801,1804,1807],{"class":37,"line":64},[35,1798,1240],{"class":67},[35,1800,1243],{"class":110},[35,1802,1803],{"class":71},"(value, ",[35,1805,1806],{"class":110},"str",[35,1808,1251],{"class":71},[35,1810,1811,1813],{"class":37,"line":75},[35,1812,1257],{"class":67},[35,1814,1815],{"class":71}," value.strip().lower()\n",[35,1817,1818,1820,1822,1824,1826,1829,1831,1834,1836,1838],{"class":37,"line":80},[35,1819,1269],{"class":67},[35,1821,1337],{"class":110},[35,1823,348],{"class":71},[35,1825,351],{"class":67},[35,1827,1828],{"class":267},"\"Unsupported type: ",[35,1830,1347],{"class":110},[35,1832,1833],{"class":71},"(value).",[35,1835,1353],{"class":110},[35,1837,1356],{"class":267},[35,1839,369],{"class":71},[14,1841,1843],{"id":1842},"duck-typing","Duck Typing",[563,1845,1846,1847,1850],{},"\"If it walks like a duck and quacks like a duck, it's a duck.\" Python cares about what an object ",[624,1848,1849],{},"can do"," (its methods\u002Fattributes), not its declared type.",[23,1852,1853],{"language":25},[27,1854,1856],{"className":29,"code":1855,"language":25,"meta":31,"style":31},"class Duck:\n    def quack(self):\n        return \"Quack!\"\n\nclass Person:\n    def quack(self):\n        return \"I'm quacking (I'm a person)\"\n\ndef make_it_quack(thing):\n    # No isinstance check at all — we just trust it has .quack()\n    return thing.quack()\n\nprint(make_it_quack(Duck()))\nprint(make_it_quack(Person()))\n",[19,1857,1858,1867,1878,1885,1889,1898,1906,1913,1917,1927,1932,1939,1943,1950],{"__ignoreMap":31},[35,1859,1860,1862,1865],{"class":37,"line":38},[35,1861,1558],{"class":67},[35,1863,1864],{"class":1230}," Duck",[35,1866,1459],{"class":71},[35,1868,1869,1872,1875],{"class":37,"line":45},[35,1870,1871],{"class":67},"    def",[35,1873,1874],{"class":1230}," quack",[35,1876,1877],{"class":71},"(self):\n",[35,1879,1880,1882],{"class":37,"line":51},[35,1881,1257],{"class":67},[35,1883,1884],{"class":267}," \"Quack!\"\n",[35,1886,1887],{"class":37,"line":57},[35,1888,61],{"emptyLinePlaceholder":60},[35,1890,1891,1893,1896],{"class":37,"line":64},[35,1892,1558],{"class":67},[35,1894,1895],{"class":1230}," Person",[35,1897,1459],{"class":71},[35,1899,1900,1902,1904],{"class":37,"line":75},[35,1901,1871],{"class":67},[35,1903,1874],{"class":1230},[35,1905,1877],{"class":71},[35,1907,1908,1910],{"class":37,"line":80},[35,1909,1257],{"class":67},[35,1911,1912],{"class":267}," \"I'm quacking (I'm a person)\"\n",[35,1914,1915],{"class":37,"line":86},[35,1916,61],{"emptyLinePlaceholder":60},[35,1918,1919,1921,1924],{"class":37,"line":92},[35,1920,1227],{"class":67},[35,1922,1923],{"class":1230}," make_it_quack",[35,1925,1926],{"class":71},"(thing):\n",[35,1928,1929],{"class":37,"line":98},[35,1930,1931],{"class":41},"    # No isinstance check at all — we just trust it has .quack()\n",[35,1933,1934,1936],{"class":37,"line":128},[35,1935,1418],{"class":67},[35,1937,1938],{"class":71}," thing.quack()\n",[35,1940,1941],{"class":37,"line":140},[35,1942,61],{"emptyLinePlaceholder":60},[35,1944,1945,1947],{"class":37,"line":145},[35,1946,131],{"class":110},[35,1948,1949],{"class":71},"(make_it_quack(Duck()))\n",[35,1951,1952,1954],{"class":37,"line":159},[35,1953,131],{"class":110},[35,1955,1956],{"class":71},"(make_it_quack(Person()))\n",[563,1958,1959,1960,1963,1964,1967],{},"This is why Python favors ",[567,1961,1962],{},"EAFP"," (\"Easier to Ask Forgiveness than Permission\") over ",[567,1965,1966],{},"LBYL"," (\"Look Before You Leap\"):",[23,1969,1970],{"language":25},[27,1971,1973],{"className":29,"code":1972,"language":25,"meta":31,"style":31},"# LBYL — checks first, then acts (race conditions possible, verbose)\nif hasattr(obj, \"quack\") and callable(obj.quack):\n    obj.quack()\n\n# EAFP — idiomatic Python: try it, handle failure\ntry:\n    obj.quack()\nexcept AttributeError:\n    print(\"Object can't quack\")\n",[19,1974,1975,1980,2003,2008,2012,2017,2024,2028,2038],{"__ignoreMap":31},[35,1976,1977],{"class":37,"line":38},[35,1978,1979],{"class":41},"# LBYL — checks first, then acts (race conditions possible, verbose)\n",[35,1981,1982,1984,1987,1990,1993,1995,1997,2000],{"class":37,"line":45},[35,1983,1448],{"class":67},[35,1985,1986],{"class":110}," hasattr",[35,1988,1989],{"class":71},"(obj, ",[35,1991,1992],{"class":267},"\"quack\"",[35,1994,688],{"class":71},[35,1996,1309],{"class":67},[35,1998,1999],{"class":110}," callable",[35,2001,2002],{"class":71},"(obj.quack):\n",[35,2004,2005],{"class":37,"line":51},[35,2006,2007],{"class":71},"    obj.quack()\n",[35,2009,2010],{"class":37,"line":57},[35,2011,61],{"emptyLinePlaceholder":60},[35,2013,2014],{"class":37,"line":64},[35,2015,2016],{"class":41},"# EAFP — idiomatic Python: try it, handle failure\n",[35,2018,2019,2022],{"class":37,"line":75},[35,2020,2021],{"class":67},"try",[35,2023,1459],{"class":71},[35,2025,2026],{"class":37,"line":80},[35,2027,2007],{"class":71},[35,2029,2030,2033,2036],{"class":37,"line":86},[35,2031,2032],{"class":67},"except",[35,2034,2035],{"class":110}," AttributeError",[35,2037,1459],{"class":71},[35,2039,2040,2042,2044,2047],{"class":37,"line":92},[35,2041,1464],{"class":110},[35,2043,348],{"class":71},[35,2045,2046],{"class":267},"\"Object can't quack\"",[35,2048,369],{"class":71},[563,2050,2051],{},"EAFP is preferred in idiomatic Python partly for readability and partly because LBYL checks can be invalidated by the time you act on them (a classic TOCTOU — time-of-check to time-of-use — bug, especially relevant with files and dicts under concurrent modification).",[14,2053,2055],{"id":2054},"checking-and-converting-types","Checking and Converting Types",[23,2057,2058],{"language":25},[27,2059,2061],{"className":29,"code":2060,"language":25,"meta":31,"style":31},"x = \"42\"\nprint(type(x))          # \u003Cclass 'str'>\nprint(int(x))            # 42          — parses a numeric string\nprint(int(\"3.14\"))       # ValueError: invalid literal for int() with base 10: '3.14'\nprint(int(float(\"3.14\"))) # 3          — go through float first, truncates toward zero\nprint(str(42))            # \"42\"\nprint(bool(\"\"))            # False — empty string is falsy\nprint(bool(\"False\"))       # True  — NON-empty string, even \"False\", is truthy!\n",[19,2062,2063,2072,2086,2100,2118,2140,2158,2176],{"__ignoreMap":31},[35,2064,2065,2067,2069],{"class":37,"line":38},[35,2066,582],{"class":71},[35,2068,104],{"class":67},[35,2070,2071],{"class":267}," \"42\"\n",[35,2073,2074,2076,2078,2080,2083],{"class":37,"line":45},[35,2075,131],{"class":110},[35,2077,348],{"class":71},[35,2079,1617],{"class":110},[35,2081,2082],{"class":71},"(x))          ",[35,2084,2085],{"class":41},"# \u003Cclass 'str'>\n",[35,2087,2088,2090,2092,2094,2097],{"class":37,"line":51},[35,2089,131],{"class":110},[35,2091,348],{"class":71},[35,2093,681],{"class":110},[35,2095,2096],{"class":71},"(x))            ",[35,2098,2099],{"class":41},"# 42          — parses a numeric string\n",[35,2101,2102,2104,2106,2108,2110,2113,2115],{"class":37,"line":57},[35,2103,131],{"class":110},[35,2105,348],{"class":71},[35,2107,681],{"class":110},[35,2109,348],{"class":71},[35,2111,2112],{"class":267},"\"3.14\"",[35,2114,798],{"class":71},[35,2116,2117],{"class":41},"# ValueError: invalid literal for int() with base 10: '3.14'\n",[35,2119,2120,2122,2124,2126,2128,2130,2132,2134,2137],{"class":37,"line":64},[35,2121,131],{"class":110},[35,2123,348],{"class":71},[35,2125,681],{"class":110},[35,2127,348],{"class":71},[35,2129,1782],{"class":110},[35,2131,348],{"class":71},[35,2133,2112],{"class":267},[35,2135,2136],{"class":71},"))) ",[35,2138,2139],{"class":41},"# 3          — go through float first, truncates toward zero\n",[35,2141,2142,2144,2146,2148,2150,2152,2155],{"class":37,"line":75},[35,2143,131],{"class":110},[35,2145,348],{"class":71},[35,2147,1806],{"class":110},[35,2149,348],{"class":71},[35,2151,613],{"class":110},[35,2153,2154],{"class":71},"))            ",[35,2156,2157],{"class":41},"# \"42\"\n",[35,2159,2160,2162,2164,2166,2168,2171,2173],{"class":37,"line":80},[35,2161,131],{"class":110},[35,2163,348],{"class":71},[35,2165,1319],{"class":110},[35,2167,348],{"class":71},[35,2169,2170],{"class":267},"\"\"",[35,2172,2154],{"class":71},[35,2174,2175],{"class":41},"# False — empty string is falsy\n",[35,2177,2178,2180,2182,2184,2186,2189,2191],{"class":37,"line":86},[35,2179,131],{"class":110},[35,2181,348],{"class":71},[35,2183,1319],{"class":110},[35,2185,348],{"class":71},[35,2187,2188],{"class":267},"\"False\"",[35,2190,798],{"class":71},[35,2192,2193],{"class":41},"# True  — NON-empty string, even \"False\", is truthy!\n",[14,2195,2197,2198],{"id":2196},"truthiness-what-counts-as-false","Truthiness — What Counts as ",[19,2199,1200],{},[563,2201,2202,2203,2206,2207,114,2209,114,2212,114,2214,114,2217,2220],{},"Every object has an implicit boolean value via ",[19,2204,2205],{},"bool(obj)",", used by ",[19,2208,1448],{},[19,2210,2211],{},"while",[19,2213,1309],{},[19,2215,2216],{},"or",[19,2218,2219],{},"not",".",[563,2222,2223,1399,2226,114,2228,114,2230,114,2232,114,2234,114,2237,114,2239,114,2242,114,2245,114,2248,2251,2252,2255,2256,2259,2260,1508,2262,2220],{},[567,2224,2225],{},"Falsy values",[19,2227,1200],{},[19,2229,1365],{},[19,2231,532],{},[19,2233,998],{},[19,2235,2236],{},"0j",[19,2238,2170],{},[19,2240,2241],{},"()",[19,2243,2244],{},"[]",[19,2246,2247],{},"{}",[19,2249,2250],{},"set()",", and any object whose ",[19,2253,2254],{},"__bool__"," (or fallback ",[19,2257,2258],{},"__len__",") returns ",[19,2261,1200],{},[19,2263,532],{},[563,2265,2266,2269,2270,114,2273,114,2275,2278,2279,2282],{},[567,2267,2268],{},"Everything else is truthy"," — including ",[19,2271,2272],{},"\"0\"",[19,2274,2188],{},[19,2276,2277],{},"[0]",", and ",[19,2280,2281],{},"{0: False}"," (all non-empty).",[23,2284,2285],{"language":25},[27,2286,2288],{"className":29,"code":2287,"language":25,"meta":31,"style":31},"values = [0, 1, \"\", \"0\", [], [0], {}, None, False, True, 0.0, -0.0]\nfor v in values:\n    print(f\"{v!r:>8} -> {bool(v)}\")\n",[19,2289,2290,2344,2358],{"__ignoreMap":31},[35,2291,2292,2295,2297,2299,2301,2303,2305,2307,2309,2311,2313,2316,2318,2321,2323,2325,2327,2329,2331,2333,2335,2337,2340,2342],{"class":37,"line":38},[35,2293,2294],{"class":71},"values ",[35,2296,104],{"class":67},[35,2298,107],{"class":71},[35,2300,532],{"class":110},[35,2302,114],{"class":71},[35,2304,111],{"class":110},[35,2306,114],{"class":71},[35,2308,2170],{"class":267},[35,2310,114],{"class":71},[35,2312,2272],{"class":267},[35,2314,2315],{"class":71},", [], [",[35,2317,532],{"class":110},[35,2319,2320],{"class":71},"], {}, ",[35,2322,1365],{"class":110},[35,2324,114],{"class":71},[35,2326,1200],{"class":110},[35,2328,114],{"class":71},[35,2330,1146],{"class":110},[35,2332,114],{"class":71},[35,2334,998],{"class":110},[35,2336,114],{"class":71},[35,2338,2339],{"class":67},"-",[35,2341,998],{"class":110},[35,2343,125],{"class":71},[35,2345,2346,2349,2352,2355],{"class":37,"line":45},[35,2347,2348],{"class":67},"for",[35,2350,2351],{"class":71}," v ",[35,2353,2354],{"class":67},"in",[35,2356,2357],{"class":71}," values:\n",[35,2359,2360,2362,2364,2366,2368,2370,2373,2376,2378,2381,2384,2387,2389,2391],{"class":37,"line":51},[35,2361,1464],{"class":110},[35,2363,348],{"class":71},[35,2365,351],{"class":67},[35,2367,1356],{"class":267},[35,2369,357],{"class":110},[35,2371,2372],{"class":71},"v",[35,2374,2375],{"class":67},"!r:>8",[35,2377,363],{"class":110},[35,2379,2380],{"class":267}," -> ",[35,2382,2383],{"class":110},"{bool",[35,2385,2386],{"class":71},"(v)",[35,2388,363],{"class":110},[35,2390,1356],{"class":267},[35,2392,369],{"class":71},[23,2394,2395],{"language":25},[27,2396,2398],{"className":29,"code":2397,"language":25,"meta":31,"style":31},"       0 -> False\n       1 -> True\n      '' -> False\n     '0' -> True\n      [] -> False\n     [0] -> True\n      {} -> False\n    None -> False\n   False -> False\n    True -> True\n     0.0 -> False\n    -0.0 -> False\n",[19,2399,2400,2412,2422,2431,2440,2450,2463,2472,2481,2490,2499,2508],{"__ignoreMap":31},[35,2401,2402,2405,2409],{"class":37,"line":38},[35,2403,2404],{"class":110},"       0",[35,2406,2408],{"class":2407},"sMKGj"," ->",[35,2410,2411],{"class":110}," False\n",[35,2413,2414,2417,2419],{"class":37,"line":45},[35,2415,2416],{"class":110},"       1",[35,2418,2408],{"class":2407},[35,2420,2421],{"class":110}," True\n",[35,2423,2424,2427,2429],{"class":37,"line":51},[35,2425,2426],{"class":267},"      ''",[35,2428,2408],{"class":2407},[35,2430,2411],{"class":110},[35,2432,2433,2436,2438],{"class":37,"line":57},[35,2434,2435],{"class":267},"     '0'",[35,2437,2408],{"class":2407},[35,2439,2421],{"class":110},[35,2441,2442,2445,2448],{"class":37,"line":64},[35,2443,2444],{"class":71},"      [] ",[35,2446,2447],{"class":2407},"->",[35,2449,2411],{"class":110},[35,2451,2452,2455,2457,2459,2461],{"class":37,"line":75},[35,2453,2454],{"class":71},"     [",[35,2456,532],{"class":110},[35,2458,271],{"class":71},[35,2460,2447],{"class":2407},[35,2462,2421],{"class":110},[35,2464,2465,2468,2470],{"class":37,"line":80},[35,2466,2467],{"class":71},"      {} ",[35,2469,2447],{"class":2407},[35,2471,2411],{"class":110},[35,2473,2474,2477,2479],{"class":37,"line":86},[35,2475,2476],{"class":110},"    None",[35,2478,2408],{"class":2407},[35,2480,2411],{"class":110},[35,2482,2483,2486,2488],{"class":37,"line":92},[35,2484,2485],{"class":110},"   False",[35,2487,2408],{"class":2407},[35,2489,2411],{"class":110},[35,2491,2492,2495,2497],{"class":37,"line":98},[35,2493,2494],{"class":110},"    True",[35,2496,2408],{"class":2407},[35,2498,2421],{"class":110},[35,2500,2501,2504,2506],{"class":37,"line":128},[35,2502,2503],{"class":110},"     0.0",[35,2505,2408],{"class":2407},[35,2507,2411],{"class":110},[35,2509,2510,2513,2515,2517],{"class":37,"line":140},[35,2511,2512],{"class":67},"    -",[35,2514,998],{"class":110},[35,2516,2408],{"class":2407},[35,2518,2411],{"class":110},[14,2520,2522],{"id":2521},"variable-naming-rules-and-conventions","Variable Naming Rules and Conventions",[23,2524,2525],{"language":25},[27,2526,2528],{"className":29,"code":2527,"language":25,"meta":31,"style":31},"# Valid identifiers: letters, digits, underscore; can't start with a digit\nvalid_name = 1\n_private_by_convention = 2\n__name_mangled_in_classes = 3\nCONSTANT_STYLE = 4          # convention only — Python has no true constants\n\n# Invalid:\n# 1st_place = \"x\"    # SyntaxError — can't start with digit\n# my-var = \"x\"       # SyntaxError — hyphen is the subtraction operator\n",[19,2529,2530,2535,2545,2555,2564,2578,2582,2587,2592],{"__ignoreMap":31},[35,2531,2532],{"class":37,"line":38},[35,2533,2534],{"class":41},"# Valid identifiers: letters, digits, underscore; can't start with a digit\n",[35,2536,2537,2540,2542],{"class":37,"line":45},[35,2538,2539],{"class":71},"valid_name ",[35,2541,104],{"class":67},[35,2543,2544],{"class":110}," 1\n",[35,2546,2547,2550,2552],{"class":37,"line":51},[35,2548,2549],{"class":71},"_private_by_convention ",[35,2551,104],{"class":67},[35,2553,2554],{"class":110}," 2\n",[35,2556,2557,2560,2562],{"class":37,"line":57},[35,2558,2559],{"class":71},"__name_mangled_in_classes ",[35,2561,104],{"class":67},[35,2563,649],{"class":110},[35,2565,2566,2569,2572,2575],{"class":37,"line":64},[35,2567,2568],{"class":110},"CONSTANT_STYLE",[35,2570,2571],{"class":67}," =",[35,2573,2574],{"class":110}," 4",[35,2576,2577],{"class":41},"          # convention only — Python has no true constants\n",[35,2579,2580],{"class":37,"line":75},[35,2581,61],{"emptyLinePlaceholder":60},[35,2583,2584],{"class":37,"line":80},[35,2585,2586],{"class":41},"# Invalid:\n",[35,2588,2589],{"class":37,"line":86},[35,2590,2591],{"class":41},"# 1st_place = \"x\"    # SyntaxError — can't start with digit\n",[35,2593,2594],{"class":37,"line":92},[35,2595,2596],{"class":41},"# my-var = \"x\"       # SyntaxError — hyphen is the subtraction operator\n",[2598,2599,2600,2613],"table",{},[2601,2602,2603],"thead",{},[2604,2605,2606,2610],"tr",{},[2607,2608,2609],"th",{},"Convention",[2607,2611,2612],{},"Meaning",[2614,2615,2616,2627,2637,2647,2657,2679],"tbody",{},[2604,2617,2618,2624],{},[2619,2620,2621],"td",{},[19,2622,2623],{},"snake_case",[2619,2625,2626],{},"Variables and functions (PEP 8).",[2604,2628,2629,2634],{},[2619,2630,2631],{},[19,2632,2633],{},"PascalCase",[2619,2635,2636],{},"Class names.",[2604,2638,2639,2644],{},[2619,2640,2641],{},[19,2642,2643],{},"UPPER_SNAKE_CASE",[2619,2645,2646],{},"Module-level constants (by convention only — still reassignable).",[2604,2648,2649,2654],{},[2619,2650,2651],{},[19,2652,2653],{},"_leading_underscore",[2619,2655,2656],{},"\"Internal use\" hint — not enforced, just a signal to other developers.",[2604,2658,2659,2664],{},[2619,2660,2661],{},[19,2662,2663],{},"__leading_double_underscore",[2619,2665,2666,2667,2670,2671,2674,2675,2678],{},"Triggers ",[567,2668,2669],{},"name mangling"," inside classes (",[19,2672,2673],{},"self.__x"," becomes ",[19,2676,2677],{},"self._ClassName__x",") — see chapter 12.",[2604,2680,2681,2686],{},[2619,2682,2683],{},[19,2684,2685],{},"__dunder__",[2619,2687,2688,2689,114,2692,2694],{},"Reserved for Python itself (",[19,2690,2691],{},"__init__",[19,2693,2258],{},") — never invent your own dunder names.",[14,2696,2698],{"id":2697},"tips-tricks","💡 Tips & Tricks",[2700,2701,2702,2732,2747,2760,2778],"ul",{},[2703,2704,2705,2711,2712,2715,2716,1508,2718,1508,2720,2723,2724,2727,2728,2731],"li",{},[567,2706,2707,2710],{},[19,2708,2709],{},"type(x).__name__"," for clean error messages"," — ",[19,2713,2714],{},"f\"Expected int, got {type(x).__name__}\""," prints ",[19,2717,681],{},[19,2719,1806],{},[19,2721,2722],{},"list"," instead of the noisy ",[19,2725,2726],{},"\u003Cclass 'int'>"," you'd get from ",[19,2729,2730],{},"type(x)"," directly in an f-string.",[2703,2733,2734,2740,2741,2743,2744,2746],{},[567,2735,2736,2739],{},[19,2737,2738],{},"sys.intern()"," for large sets of repeated strings"," — In hot paths comparing many repeated strings (e.g., parser tokens), ",[19,2742,2738],{}," guarantees identical strings share one object, making ",[19,2745,872],{}," comparison valid and fast — CPython already auto-interns short identifier-like literals, but not all strings.",[2703,2748,2749,2711,2752,2755,2756,2759],{},[567,2750,2751],{},"Underscore digit separators",[19,2753,2754],{},"1_000_000"," and ",[19,2757,2758],{},"0x_FF_FF"," are valid literals since Python 3.6; use them for readability in large numeric constants.",[2703,2761,2762,2711,2770,2773,2774,2777],{},[567,2763,2764,1505,2766,2769],{},[19,2765,1141],{},[19,2767,2768],{},"|"," union syntax (3.10+)",[19,2771,2772],{},"isinstance(x, int | float)"," works identically to the tuple form ",[19,2775,2776],{},"isinstance(x, (int, float))"," and reads closer to type-hint syntax.",[2703,2779,2780,2785,2786,2789],{},[567,2781,2782,2784],{},[19,2783,1365],{}," as a sentinel default, never a mutable literal"," — Use ",[19,2787,2788],{},"def f(cache=None): cache = cache if cache is not None else {}"," instead of a mutable default — chapter 05 explains exactly why the mutable form is dangerous.",[14,2791,2793],{"id":2792},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[2700,2795,2796,2841,2861,2891,2921],{},[2703,2797,2798,2806,2807,2810,2811,2814,2815,2817,2818,2821,2822,2824,2825,2831,2832,2834,2835,2837,2838,2840],{},[567,2799,2800,2801,1543,2803,2805],{},"Small integer caching (",[19,2802,872],{},[19,2804,975],{}," on ints)"," — CPython pre-allocates and caches integers in ",[19,2808,2809],{},"[-5, 256]"," as singletons. ",[19,2812,2813],{},"a = 100; b = 100; a is b"," is ",[19,2816,1146],{},", but ",[19,2819,2820],{},"a = 1000; b = 1000; a is b"," is often ",[19,2823,1200],{}," (implementation detail, not guaranteed by the language spec) because they're separately allocated objects with equal value but different identity. ",[567,2826,2827,2828,2830],{},"Never use ",[19,2829,872],{}," to compare integer values"," — always use ",[19,2833,975],{},"; ",[19,2836,872],{}," is only correct for ",[19,2839,1365],{},", and for deliberate singleton\u002Fsentinel checks.",[2703,2842,2843,2846,2847,2850,2851,2853,2854,2857,2858,2860],{},[567,2844,2845],{},"String interning is inconsistent across literal forms"," — Short strings that look like identifiers (",[19,2848,2849],{},"\"hello\"",") are often interned by CPython and compare equal with ",[19,2852,872],{},", but strings built at runtime (",[19,2855,2856],{},"\"\".join([\"h\",\"e\",\"l\",\"l\",\"o\"])",") usually are not, even with equal content. Relying on ",[19,2859,872],{}," for string equality is a latent bug that \"works in testing\" and fails in production.",[2703,2862,2863,2711,2871,2814,2874,2876,2877,2880,2881,2883,2884,2886,2887,2890],{},[567,2864,2865,2867,2868,2870],{},[19,2866,1319],{}," being a subclass of ",[19,2869,681],{}," breaks naive type dispatch",[19,2872,2873],{},"isinstance(True, int)",[19,2875,1146],{},", so a function branching only on ",[19,2878,2879],{},"isinstance(x, int)"," silently also matches booleans, which can produce nonsensical results like treating ",[19,2882,1146],{}," as the integer ",[19,2885,111],{}," in arithmetic contexts you didn't intend. Explicitly exclude booleans (",[19,2888,2889],{},"isinstance(x, int) and not isinstance(x, bool)",") when the distinction matters (e.g., validating \"this must be a count, not a flag\").",[2703,2892,2893,2711,2896,2814,2899,2901,2902,2755,2905,2908,2909,2912,2913,2916,2917,2920],{},[567,2894,2895],{},"Floating-point representation is binary, not decimal",[19,2897,2898],{},"0.1 + 0.2 == 0.3",[19,2900,1200],{}," because ",[19,2903,2904],{},"0.1",[19,2906,2907],{},"0.2"," have no exact binary (base-2) fractional representation — the same reason ",[19,2910,2911],{},"1\u002F3"," has no exact finite decimal representation. Use ",[19,2914,2915],{},"math.isclose(0.1 + 0.2, 0.3)"," for float comparisons, or the ",[19,2918,2919],{},"decimal.Decimal"," type for money\u002Fprecision-critical arithmetic.",[2703,2922,2923,2931,2932,2935,2936,2939,2940,2943,2944,2947,2948,2951,2952,2955,2956,2220],{},[567,2924,2925,2814,2928,2930],{},[19,2926,2927],{},"0.0 == -0.0",[19,2929,1146],{},", but they are distinct bit patterns"," — IEEE-754 defines signed zero. ",[19,2933,2934],{},"1 \u002F 0.0"," raises ",[19,2937,2938],{},"ZeroDivisionError"," in Python (unlike C, which yields ",[19,2941,2942],{},"inf","), but ",[19,2945,2946],{},"1 \u002F -0.0"," — if you get a ",[19,2949,2950],{},"-0.0"," from a computation rather than division by an int-cast zero — behaves per IEEE-754 rules; this rarely matters, but has bitten numerical code comparing ",[19,2953,2954],{},"float('-0.0')"," bit-for-bit via ",[19,2957,2958],{},"struct.pack",[14,2960,2962],{"id":2961},"spot-the-bug","🧠 Spot the Bug",[563,2964,2965],{},"What does this print, and why does it differ from what most beginners expect?",[23,2967,2968],{"language":25},[27,2969,2971],{"className":29,"code":2970,"language":25,"meta":31,"style":31},"a = 256\nb = 256\nprint(a is b)     # ?\n\nc = 257\nd = 257\nprint(c is d)     # ?\n\ne = -5\nf = -5\nprint(e is f)     # ?\n\ng = -6\nh = -6\nprint(g is h)     # ?\n",[19,2972,2973,2982,2991,3005,3009,3019,3027,3041,3045,3057,3068,3082,3086,3098,3109],{"__ignoreMap":31},[35,2974,2975,2977,2979],{"class":37,"line":38},[35,2976,248],{"class":71},[35,2978,104],{"class":67},[35,2980,2981],{"class":110}," 256\n",[35,2983,2984,2987,2989],{"class":37,"line":45},[35,2985,2986],{"class":71},"b ",[35,2988,104],{"class":67},[35,2990,2981],{"class":110},[35,2992,2993,2995,2997,2999,3002],{"class":37,"line":51},[35,2994,131],{"class":110},[35,2996,869],{"class":71},[35,2998,872],{"class":67},[35,3000,3001],{"class":71}," b)     ",[35,3003,3004],{"class":41},"# ?\n",[35,3006,3007],{"class":37,"line":57},[35,3008,61],{"emptyLinePlaceholder":60},[35,3010,3011,3014,3016],{"class":37,"line":64},[35,3012,3013],{"class":71},"c ",[35,3015,104],{"class":67},[35,3017,3018],{"class":110}," 257\n",[35,3020,3021,3023,3025],{"class":37,"line":75},[35,3022,1599],{"class":71},[35,3024,104],{"class":67},[35,3026,3018],{"class":110},[35,3028,3029,3031,3034,3036,3039],{"class":37,"line":80},[35,3030,131],{"class":110},[35,3032,3033],{"class":71},"(c ",[35,3035,872],{"class":67},[35,3037,3038],{"class":71}," d)     ",[35,3040,3004],{"class":41},[35,3042,3043],{"class":37,"line":86},[35,3044,61],{"emptyLinePlaceholder":60},[35,3046,3047,3050,3052,3054],{"class":37,"line":92},[35,3048,3049],{"class":71},"e ",[35,3051,104],{"class":67},[35,3053,933],{"class":67},[35,3055,3056],{"class":110},"5\n",[35,3058,3059,3062,3064,3066],{"class":37,"line":98},[35,3060,3061],{"class":71},"f ",[35,3063,104],{"class":67},[35,3065,933],{"class":67},[35,3067,3056],{"class":110},[35,3069,3070,3072,3075,3077,3080],{"class":37,"line":128},[35,3071,131],{"class":110},[35,3073,3074],{"class":71},"(e ",[35,3076,872],{"class":67},[35,3078,3079],{"class":71}," f)     ",[35,3081,3004],{"class":41},[35,3083,3084],{"class":37,"line":140},[35,3085,61],{"emptyLinePlaceholder":60},[35,3087,3088,3091,3093,3095],{"class":37,"line":145},[35,3089,3090],{"class":71},"g ",[35,3092,104],{"class":67},[35,3094,933],{"class":67},[35,3096,3097],{"class":110},"6\n",[35,3099,3100,3103,3105,3107],{"class":37,"line":159},[35,3101,3102],{"class":71},"h ",[35,3104,104],{"class":67},[35,3106,933],{"class":67},[35,3108,3097],{"class":110},[35,3110,3111,3113,3116,3118,3121],{"class":37,"line":169},[35,3112,131],{"class":110},[35,3114,3115],{"class":71},"(g ",[35,3117,872],{"class":67},[35,3119,3120],{"class":71}," h)     ",[35,3122,3004],{"class":41},[3124,3125,3126,3130,3154,3189],"details",{},[3127,3128,3129],"summary",{},"Answer",[563,3131,3132,3135,3136,114,3138,3141,3142,114,3144,3135,3147,114,3149,3141,3152,2220],{},[19,3133,3134],{},"a is b"," → ",[19,3137,1146],{},[19,3139,3140],{},"c is d"," → usually ",[19,3143,1200],{},[19,3145,3146],{},"e is f",[19,3148,1146],{},[19,3150,3151],{},"g is h",[19,3153,1200],{},[563,3155,3156,3157,3159,3160,3163,3164,3167,3168,3170,3171,1515,3173,3176,3177,3180,3181,3170,3183,3185,3186,2220],{},"CPython caches integer objects in the range ",[19,3158,2809],{}," inclusive at interpreter startup as a performance optimization (small integers are used constantly, so reusing objects avoids repeated allocation). ",[19,3161,3162],{},"256"," falls inside that range, so both names bind to the ",[624,3165,3166],{},"same"," cached object — ",[19,3169,872],{}," returns ",[19,3172,1146],{},[19,3174,3175],{},"257"," falls outside it, so each literal typically creates a ",[624,3178,3179],{},"new"," int object — ",[19,3182,872],{},[19,3184,1200],{}," (though in the same statement\u002Fconstant-folding context the compiler might occasionally intern identical literals — never rely on this). The same boundary applies at ",[19,3187,3188],{},"-5",[563,3190,3191,1399,3194,3196,3197,3199,3200,3202,3203,3205],{},[567,3192,3193],{},"The lesson",[19,3195,872],{}," tests object identity, not value equality — it only ever gives value-correct results for integers by accident of an implementation detail (the small-int cache), never by language guarantee. Always use ",[19,3198,975],{}," for comparing values, and reserve ",[19,3201,872],{}," for ",[19,3204,1365],{},", sentinels, and deliberate singleton checks.",[14,3207,3209],{"id":3208},"key-takeaways","Key Takeaways",[2700,3211,3212,3215,3224,3237,3247],{},[2703,3213,3214],{},"Names are references to objects, not boxes containing values — assignment binds, it never copies.",[2703,3216,3217,3218,3221,3222,2220],{},"Python is dynamically but ",[624,3219,3220],{},"strongly"," typed: types live on objects, and there's no silent cross-type coercion like JavaScript's ",[19,3223,664],{},[2703,3225,3226,3228,3229,3231,3232,3234,3235,2220],{},[19,3227,681],{}," has arbitrary precision (no overflow); ",[19,3230,1782],{}," is IEEE-754 double precision (subject to rounding); ",[19,3233,1319],{}," is a subclass of ",[19,3236,681],{},[2703,3238,3239,3240,3242,3243,3246],{},"Prefer ",[19,3241,1546],{}," over ",[19,3244,3245],{},"type() =="," for type checks — it respects inheritance and duck typing.",[2703,3248,2827,3249,3251,3252,3254,3255,3257],{},[19,3250,872],{}," to compare values (especially ints and strings) — the small-int cache and string interning are implementation details, not guarantees. Use ",[19,3253,872],{}," only for ",[19,3256,1365],{}," and sentinel\u002Fsingleton checks.",[3259,3260,3261],"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 .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 .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}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":31,"searchDepth":45,"depth":45,"links":3263},[3264,3266,3267,3271,3273,3274,3275,3277,3278,3279,3280,3281],{"id":16,"depth":45,"text":3265},"The Object Model — Every Value Is a Heap-Allocated PyObject",{"id":560,"depth":45,"text":561},{"id":719,"depth":45,"text":720,"children":3268},[3269],{"id":1362,"depth":51,"text":3270},"None is not \"falsy zero\" — it's a distinct singleton",{"id":1539,"depth":45,"text":3272},"type() vs isinstance()",{"id":1842,"depth":45,"text":1843},{"id":2054,"depth":45,"text":2055},{"id":2196,"depth":45,"text":3276},"Truthiness — What Counts as False",{"id":2521,"depth":45,"text":2522},{"id":2697,"depth":45,"text":2698},{"id":2792,"depth":45,"text":2793},{"id":2961,"depth":45,"text":2962},{"id":3208,"depth":45,"text":3209},"md",{},"\u002Fpython\u002F02-variables-and-data-types",{"title":5,"description":31},"python\u002F02-variables-and-data-types","sTSL7j4QOj7cqnD_OduZaRMpsx63cpU1YjnaGDpkQso",1789924651256]