[{"data":1,"prerenderedAt":2864},["ShallowReactive",2],{"page-\u002Fpython\u002F02-variables-and-data-types":3},{"id":4,"title":5,"body":6,"description":30,"extension":2858,"meta":2859,"navigation":80,"path":2860,"seo":2861,"stem":2862,"__hash__":2863},"content\u002Fpython\u002F02-variables-and-data-types.md","02 — Variables & Data Types",{"type":7,"value":8,"toc":2823},"minimark",[9,13,154,257,422,482,629,803,928,1098,1287,1455,1568,1728,1948,2029,2124,2246,2333,2459,2656,2819],[10,11,5],"h1",{"id":12},"_02-variables-data-types",[14,15,17,22,67,108],"question-wrapper",{"language":16},"python",[18,19,21],"h3",{"id":20},"q1-which-statement-correctly-describes-pythons-object-model","Q1. Which statement correctly describes Python's object model?",[23,24,25],"code-wrapper",{"language":16},[26,27,31],"pre",{"className":28,"code":29,"language":16,"meta":30,"style":30},"language-python shiki shiki-themes github-light github-dark","x = 42\ndef greet(): pass\n","",[32,33,34,51],"code",{"__ignoreMap":30},[35,36,39,43,47],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"ssxIu","x ",[35,44,46],{"class":45},"svdQ7","=",[35,48,50],{"class":49},"snvgF"," 42\n",[35,52,54,57,61,64],{"class":37,"line":53},2,[35,55,56],{"class":45},"def",[35,58,60],{"class":59},"sIsaT"," greet",[35,62,63],{"class":41},"(): ",[35,65,66],{"class":45},"pass\n",[68,69,72,87,93,99],"ul",{"className":70},[71],"contains-task-list",[73,74,77,82,83,86],"li",{"className":75},[76],"task-list-item",[78,79],"input",{"disabled":80,"type":81},true,"checkbox"," Only class instances are objects; primitives like ",[32,84,85],{},"int"," and functions are special language constructs",[73,88,90,92],{"className":89},[76],[78,91],{"disabled":80,"type":81}," Everything referenced by a name — integers, strings, functions, classes, and modules — is an object with a type and identity",[73,94,96,98],{"className":95},[76],[78,97],{"disabled":80,"type":81}," Only mutable values (lists, dicts) are objects; immutable values are stored inline, not as objects",[73,100,102,104,105],{"className":101},[76],[78,103],{"disabled":80,"type":81}," Objects exist only after you explicitly instantiate a class with ",[32,106,107],{},"()",[109,110,111,115,123],"details",{},[112,113,114],"summary",{},"Show Answer",[116,117,118,122],"p",{},[119,120,121],"strong",{},"Answer:"," B — Everything referenced by a name — integers, strings, functions, classes, and modules — is an object with a type and identity",[116,124,125,128,129,132,133,136,137,139,140,143,144,147,148,139,150,153],{},[119,126,127],{},"Explanation:"," In Python, \"everything is an object\" is not a slogan but a literal implementation fact: ",[32,130,131],{},"42",", ",[32,134,135],{},"greet",", and even the ",[32,138,85],{}," and ",[32,141,142],{},"function"," types themselves are objects with a type, an identity (",[32,145,146],{},"id()","), and typically attributes. Option A is the kind of assumption carried over from languages with true primitive types, which Python does not have. Option C is backwards — immutability affects whether an object can change in place, not whether it \"is\" an object. Option D is wrong because literals like ",[32,149,131],{},[32,151,152],{},"\"hi\""," are objects the moment they're created, with no explicit constructor call required.",[14,155,156,167,194,233],{"language":16},[18,157,159,160,162,163,166],{"id":158},"q2-what-happens-when-a-name-already-bound-to-an-int-is-reassigned-to-a-str","Q2. What happens when a name already bound to an ",[32,161,85],{}," is reassigned to a ",[32,164,165],{},"str","?",[23,168,169],{"language":16},[26,170,172],{"className":28,"code":171,"language":16,"meta":30,"style":30},"status = 200\nstatus = \"OK\"\n",[32,173,174,184],{"__ignoreMap":30},[35,175,176,179,181],{"class":37,"line":38},[35,177,178],{"class":41},"status ",[35,180,46],{"class":45},[35,182,183],{"class":49}," 200\n",[35,185,186,188,190],{"class":37,"line":53},[35,187,178],{"class":41},[35,189,46],{"class":45},[35,191,193],{"class":192},"sJ6F3"," \"OK\"\n",[68,195,197,207,213,223],{"className":196},[71],[73,198,200,202,203,206],{"className":199},[76],[78,201],{"disabled":80,"type":81}," A ",[32,204,205],{},"TypeError",", because a variable's type cannot change after first assignment",[73,208,210,212],{"className":209},[76],[78,211],{"disabled":80,"type":81}," This is legal — Python is dynamically typed, so a name can be rebound to any object regardless of the previous object's type",[73,214,216,218,219,222],{"className":215},[76],[78,217],{"disabled":80,"type":81}," The assignment silently converts ",[32,220,221],{},"\"OK\""," to an integer to match the variable's original type",[73,224,226,228,229,232],{"className":225},[76],[78,227],{"disabled":80,"type":81}," It works only if both statements are inside the same ",[32,230,231],{},"with"," block",[109,234,235,237,242],{},[112,236,114],{},[116,238,239,241],{},[119,240,121],{}," B — This is legal — Python is dynamically typed, so a name can be rebound to any object regardless of the previous object's type",[116,243,244,246,247,250,251,253,254,256],{},[119,245,127],{}," Python variables are just names in a namespace bound to objects; the name ",[32,248,249],{},"status"," has no fixed type of its own, so rebinding it to a ",[32,252,165],{}," after an ",[32,255,85],{}," is completely legal at runtime. Option A confuses Python with statically-typed languages that give variables a fixed declared type. Option C invents a coercion Python never performs implicitly between unrelated types. Option D's premise is irrelevant — no such scoping restriction exists.",[14,258,259,269,323,370],{"language":16},[18,260,262,263,139,266,166],{"id":261},"q3-what-is-the-core-difference-between-is-and","Q3. What is the core difference between ",[32,264,265],{},"is",[32,267,268],{},"==",[23,270,271],{"language":16},[26,272,274],{"className":28,"code":273,"language":16,"meta":30,"style":30},"a = [1, 2, 3]\nb = [1, 2, 3]\n",[32,275,276,302],{"__ignoreMap":30},[35,277,278,281,283,286,289,291,294,296,299],{"class":37,"line":38},[35,279,280],{"class":41},"a ",[35,282,46],{"class":45},[35,284,285],{"class":41}," [",[35,287,288],{"class":49},"1",[35,290,132],{"class":41},[35,292,293],{"class":49},"2",[35,295,132],{"class":41},[35,297,298],{"class":49},"3",[35,300,301],{"class":41},"]\n",[35,303,304,307,309,311,313,315,317,319,321],{"class":37,"line":53},[35,305,306],{"class":41},"b ",[35,308,46],{"class":45},[35,310,285],{"class":41},[35,312,288],{"class":49},[35,314,132],{"class":41},[35,316,293],{"class":49},[35,318,132],{"class":41},[35,320,298],{"class":49},[35,322,301],{"class":41},[68,324,326,338,353,359],{"className":325},[71],[73,327,329,331,332,334,335,337],{"className":328},[76],[78,330],{"disabled":80,"type":81}," ",[32,333,265],{}," checks value equality; ",[32,336,268],{}," checks object identity",[73,339,341,331,343,345,346,348,349,352],{"className":340},[76],[78,342],{"disabled":80,"type":81},[32,344,265],{}," checks object identity (same object in memory); ",[32,347,268],{}," checks value equality (calls ",[32,350,351],{},"__eq__",")",[73,354,356,358],{"className":355},[76],[78,357],{"disabled":80,"type":81}," They are fully interchangeable for all built-in types",[73,360,362,331,364,366,367,369],{"className":361},[76],[78,363],{"disabled":80,"type":81},[32,365,265],{}," only works on numbers; ",[32,368,268],{}," only works on strings",[109,371,372,374,385],{},[112,373,114],{},[116,375,376,378,379,345,381,348,383,352],{},[119,377,121],{}," B — ",[32,380,265],{},[32,382,268],{},[32,384,351],{},[116,386,387,331,389,391,392,395,396,398,399,401,402,405,406,409,410,405,413,416,417,139,419,421],{},[119,388,127],{},[32,390,265],{}," answers \"are these the same object?\" (equivalent to comparing ",[32,393,394],{},"id(a) == id(b)","), while ",[32,397,268],{}," answers \"do these compare equal?\" by invoking ",[32,400,351],{},". In the code above, ",[32,403,404],{},"a == b"," is ",[32,407,408],{},"True"," (same contents) but ",[32,411,412],{},"a is b",[32,414,415],{},"False"," (two distinct list objects). Option A states the definitions backwards. Option C is a common trap — for mutable objects and most non-cached immutables, ",[32,418,265],{},[32,420,268],{}," diverge exactly as shown here. Option D is simply false; both operators work across types.",[14,423,424,431,458],{},[18,425,427,428,430],{"id":426},"q4-what-does-the-built-in-id-function-return","Q4. What does the built-in ",[32,429,146],{}," function return?",[68,432,434,440,446,452],{"className":433},[71],[73,435,437,439],{"className":436},[76],[78,438],{"disabled":80,"type":81}," The object's type name as a string",[73,441,443,445],{"className":442},[76],[78,444],{"disabled":80,"type":81}," An integer that is guaranteed unique among currently alive objects during the program's run — in CPython, typically the object's memory address",[73,447,449,451],{"className":448},[76],[78,450],{"disabled":80,"type":81}," A cryptographic hash of the object's contents",[73,453,455,457],{"className":454},[76],[78,456],{"disabled":80,"type":81}," The line number where the object was created",[109,459,460,462,467],{},[112,461,114],{},[116,463,464,466],{},[119,465,121],{}," B — An integer that is guaranteed unique among currently alive objects during the program's run — in CPython, typically the object's memory address",[116,468,469,331,471,473,474,477,478,481],{},[119,470,127],{},[32,472,146],{}," returns a value guaranteed to be unique and constant for an object for its lifetime; CPython implements this as the object's memory address, but that detail is implementation-specific and should not be relied on beyond identity comparison. Option A describes ",[32,475,476],{},"type(obj).__name__",". Option C describes ",[32,479,480],{},"hash()",", which is a different, value-based concept and is not guaranteed unique. Option D describes nothing Python tracks by default.",[14,483,484,488,558],{},[18,485,487],{"id":486},"q5-which-of-these-is-the-correct-classification-of-built-in-types-by-mutability","Q5. Which of these is the correct classification of built-in types by mutability?",[68,489,491,514,543,549],{"className":490},[71],[73,492,494,496,497,132,499,132,501,504,505,132,508,132,511],{"className":493},[76],[78,495],{"disabled":80,"type":81}," Mutable: ",[32,498,85],{},[32,500,165],{},[32,502,503],{},"tuple"," — Immutable: ",[32,506,507],{},"list",[32,509,510],{},"dict",[32,512,513],{},"set",[73,515,517,496,519,132,521,132,523,132,525,504,528,132,530,132,533,132,535,132,537,132,540],{"className":516},[76],[78,518],{"disabled":80,"type":81},[32,520,507],{},[32,522,510],{},[32,524,513],{},[32,526,527],{},"bytearray",[32,529,85],{},[32,531,532],{},"float",[32,534,165],{},[32,536,503],{},[32,538,539],{},"bool",[32,541,542],{},"frozenset",[73,544,546,548],{"className":545},[76],[78,547],{"disabled":80,"type":81}," All built-in container types are mutable; only numbers are immutable",[73,550,552,554,555],{"className":551},[76],[78,553],{"disabled":80,"type":81}," Mutability is a runtime flag you must set explicitly with ",[32,556,557],{},"mutable=True",[109,559,560,562,587],{},[112,561,114],{},[116,563,564,566,567,132,569,132,571,132,573,504,575,132,577,132,579,132,581,132,583,132,585],{},[119,565,121],{}," B — Mutable: ",[32,568,507],{},[32,570,510],{},[32,572,513],{},[32,574,527],{},[32,576,85],{},[32,578,532],{},[32,580,165],{},[32,582,503],{},[32,584,539],{},[32,586,542],{},[116,588,589,331,591,132,593,132,595,597,598,600,601,132,604,132,607,610,611,132,613,132,615,132,617,132,619,597,621,623,624,139,626,628],{},[119,590,127],{},[32,592,507],{},[32,594,510],{},[32,596,513],{},", and ",[32,599,527],{}," support in-place mutation (",[32,602,603],{},"append",[32,605,606],{},"__setitem__",[32,608,609],{},"add",", and friends), whereas ",[32,612,85],{},[32,614,532],{},[32,616,165],{},[32,618,503],{},[32,620,539],{},[32,622,542],{}," cannot be changed after creation — any \"modification\" actually produces a new object. Option A has the classification exactly backwards. Option C is wrong because ",[32,625,503],{},[32,627,542],{}," are containers that are nonetheless immutable. Option D describes a mechanism Python does not have — mutability is a property of the type, not a per-instance flag.",[14,630,631,646,701,753],{"language":16},[18,632,634,635,139,638,641,642,645],{"id":633},"q6-what-is-the-difference-between-typeobj-someclass-and-isinstanceobj-someclass-when-obj-might-be-an-instance-of-a-subclass","Q6. What is the difference between ",[32,636,637],{},"type(obj) == SomeClass",[32,639,640],{},"isinstance(obj, SomeClass)"," when ",[32,643,644],{},"obj"," might be an instance of a subclass?",[23,647,648],{"language":16},[26,649,651],{"className":28,"code":650,"language":16,"meta":30,"style":30},"class Animal: pass\nclass Dog(Animal): pass\n\nd = Dog()\n",[32,652,653,666,684,690],{"__ignoreMap":30},[35,654,655,658,661,664],{"class":37,"line":38},[35,656,657],{"class":45},"class",[35,659,660],{"class":59}," Animal",[35,662,663],{"class":41},": ",[35,665,66],{"class":45},[35,667,668,670,673,676,679,682],{"class":37,"line":53},[35,669,657],{"class":45},[35,671,672],{"class":59}," Dog",[35,674,675],{"class":41},"(",[35,677,678],{"class":59},"Animal",[35,680,681],{"class":41},"): ",[35,683,66],{"class":45},[35,685,687],{"class":37,"line":686},3,[35,688,689],{"emptyLinePlaceholder":80},"\n",[35,691,693,696,698],{"class":37,"line":692},4,[35,694,695],{"class":41},"d ",[35,697,46],{"class":45},[35,699,700],{"class":41}," Dog()\n",[68,702,704,710,735,745],{"className":703},[71],[73,705,707,709],{"className":706},[76],[78,708],{"disabled":80,"type":81}," They always behave identically for every object",[73,711,713,331,715,405,718,720,721,724,725,405,728,730,731,734],{"className":712},[76],[78,714],{"disabled":80,"type":81},[32,716,717],{},"type(d) == Animal",[32,719,415],{}," for a ",[32,722,723],{},"Dog"," instance, while ",[32,726,727],{},"isinstance(d, Animal)",[32,729,408],{},", because ",[32,732,733],{},"isinstance"," accounts for inheritance",[73,736,738,331,740,405,742,744],{"className":737},[76],[78,739],{"disabled":80,"type":81},[32,741,717],{},[32,743,408],{}," because Python treats subclasses as equal types",[73,746,748,331,750,752],{"className":747},[76],[78,749],{"disabled":80,"type":81},[32,751,733],{}," only works with built-in types, not user-defined classes",[109,754,755,757,773],{},[112,756,114],{},[116,758,759,378,761,405,763,720,765,724,767,405,769,730,771,734],{},[119,760,121],{},[32,762,717],{},[32,764,415],{},[32,766,723],{},[32,768,727],{},[32,770,408],{},[32,772,733],{},[116,774,775,331,777,780,781,783,784,786,787,789,790,792,793,795,796,799,800,802],{},[119,776,127],{},[32,778,779],{},"type(d)"," returns the exact class ",[32,782,723],{},", which does not equal ",[32,785,678],{},", whereas ",[32,788,733],{}," walks the MRO and correctly reports that a ",[32,791,723],{}," \"is-an\" ",[32,794,678],{},". This distinction matters constantly in real code that accepts subclasses polymorphically. Option A ignores exactly this divergence. Option C misunderstands ",[32,797,798],{},"type()",", which never treats a subclass as equal to its parent. Option D is false — ",[32,801,733],{}," works uniformly across built-in and user-defined classes.",[14,804,805,819,855,895],{"language":16},[18,806,808,809,812,813,816,817,166],{"id":807},"q7-what-happens-when-you-execute-b-a-where-a-is-a-list","Q7. What happens when you execute ",[32,810,811],{},"b = a"," where ",[32,814,815],{},"a"," is a ",[32,818,507],{},[23,820,821],{"language":16},[26,822,824],{"className":28,"code":823,"language":16,"meta":30,"style":30},"a = [1, 2, 3]\nb = a\n",[32,825,826,846],{"__ignoreMap":30},[35,827,828,830,832,834,836,838,840,842,844],{"class":37,"line":38},[35,829,280],{"class":41},[35,831,46],{"class":45},[35,833,285],{"class":41},[35,835,288],{"class":49},[35,837,132],{"class":41},[35,839,293],{"class":49},[35,841,132],{"class":41},[35,843,298],{"class":49},[35,845,301],{"class":41},[35,847,848,850,852],{"class":37,"line":53},[35,849,306],{"class":41},[35,851,46],{"class":45},[35,853,854],{"class":41}," a\n",[68,856,858,867,878,886],{"className":857},[71],[73,859,861,863,864],{"className":860},[76],[78,862],{"disabled":80,"type":81}," A new, independent copy of the list is created and bound to ",[32,865,866],{},"b",[73,868,870,331,872,874,875,877],{"className":869},[76],[78,871],{"disabled":80,"type":81},[32,873,866],{}," becomes a second name bound to the exact same list object as ",[32,876,815],{},"; no copying occurs",[73,879,881,331,883,885],{"className":880},[76],[78,882],{"disabled":80,"type":81},[32,884,866],{}," is bound to a lazily-copied \"view\" that only copies on first mutation",[73,887,889,891,892,894],{"className":888},[76],[78,890],{"disabled":80,"type":81}," This raises a ",[32,893,205],{}," because lists cannot be reassigned",[109,896,897,899,907],{},[112,898,114],{},[116,900,901,378,903,874,905,877],{},[119,902,121],{},[32,904,866],{},[32,906,815],{},[116,908,909,911,912,139,914,916,917,405,919,921,922,924,925,927],{},[119,910,127],{}," Assignment in Python never copies an object; it binds a name to whatever object is on the right-hand side. So ",[32,913,815],{},[32,915,866],{}," here are two labels for one list, and ",[32,918,412],{},[32,920,408],{}," — mutating through either name affects what the other sees. Option A describes copy semantics found in some other languages, not Python's default ",[32,923,46],{},". Option C describes copy-on-write, a strategy CPython does not use for ",[32,926,507],{}," assignment. Option D is false; reassignment is always legal.",[14,929,930,934,1008,1052],{"language":16},[18,931,933],{"id":932},"q8-given-the-following-what-is-printed-and-why","Q8. Given the following, what is printed, and why?",[23,935,936],{"language":16},[26,937,939],{"className":28,"code":938,"language":16,"meta":30,"style":30},"a = 100\nb = 100\nprint(a is b)\n\nx = 1000\ny = 1000\nprint(x is y)\n",[32,940,941,950,958,971,975,985,995],{"__ignoreMap":30},[35,942,943,945,947],{"class":37,"line":38},[35,944,280],{"class":41},[35,946,46],{"class":45},[35,948,949],{"class":49}," 100\n",[35,951,952,954,956],{"class":37,"line":53},[35,953,306],{"class":41},[35,955,46],{"class":45},[35,957,949],{"class":49},[35,959,960,963,966,968],{"class":37,"line":686},[35,961,962],{"class":49},"print",[35,964,965],{"class":41},"(a ",[35,967,265],{"class":45},[35,969,970],{"class":41}," b)\n",[35,972,973],{"class":37,"line":692},[35,974,689],{"emptyLinePlaceholder":80},[35,976,978,980,982],{"class":37,"line":977},5,[35,979,42],{"class":41},[35,981,46],{"class":45},[35,983,984],{"class":49}," 1000\n",[35,986,988,991,993],{"class":37,"line":987},6,[35,989,990],{"class":41},"y ",[35,992,46],{"class":45},[35,994,984],{"class":49},[35,996,998,1000,1003,1005],{"class":37,"line":997},7,[35,999,962],{"class":49},[35,1001,1002],{"class":41},"(x ",[35,1004,265],{"class":45},[35,1006,1007],{"class":41}," y)\n",[68,1009,1011,1022,1032,1042],{"className":1010},[71],[73,1012,1014,331,1016,1018,1019,1021],{"className":1013},[76],[78,1015],{"disabled":80,"type":81},[32,1017,408],{}," then ",[32,1020,408],{}," — CPython always caches and reuses every integer object",[73,1023,1025,331,1027,1018,1029,1031],{"className":1024},[76],[78,1026],{"disabled":80,"type":81},[32,1028,408],{},[32,1030,415],{}," — CPython pre-caches and interns small integers in the range -5 to 256, but not arbitrary larger integers, which may or may not be separate objects depending on context",[73,1033,1035,331,1037,1018,1039,1041],{"className":1034},[76],[78,1036],{"disabled":80,"type":81},[32,1038,415],{},[32,1040,415],{}," — integers are never cached in CPython",[73,1043,1045,331,1047,1018,1049,1051],{"className":1044},[76],[78,1046],{"disabled":80,"type":81},[32,1048,415],{},[32,1050,408],{}," — only large integers are cached to save memory",[109,1053,1054,1056,1064],{},[112,1055,114],{},[116,1057,1058,378,1060,1018,1062,1031],{},[119,1059,121],{},[32,1061,408],{},[32,1063,415],{},[116,1065,1066,331,1068,1071,1072,1074,1075,1077,1078,1081,1082,1085,1086,1088,1089,1091,1092,1094,1095,1097],{},[119,1067,127],{},[119,1069,1070],{},"Performance"," — as a memory optimization, CPython pre-allocates and reuses a singleton object for every integer from -5 to 256, so ",[32,1073,412],{}," is reliably ",[32,1076,408],{}," for ",[32,1079,1080],{},"100",". Numbers outside that range are ordinarily created fresh each time (",[32,1083,1084],{},"x is y"," is typically ",[32,1087,415],{},", though this is an implementation detail that can vary — e.g. constant-folding within the same compiled code unit can sometimes make it ",[32,1090,408],{}," too). The trap is treating ",[32,1093,265],{}," as safe for comparing arbitrary integers just because it \"worked\" during testing with small numbers; always use ",[32,1096,268],{}," for integer value comparison.",[14,1099,1100,1104,1195,1234],{"language":16},[18,1101,1103],{"id":1102},"q9-what-is-the-most-accurate-description-of-cpython-string-interning","Q9. What is the most accurate description of CPython string interning?",[23,1105,1106],{"language":16},[26,1107,1109],{"className":28,"code":1108,"language":16,"meta":30,"style":30},"s1 = \"hello\"\ns2 = \"hello\"\nprint(s1 is s2)\n\ns3 = \"\".join([\"h\", \"e\", \"l\", \"l\", \"o\"])\nprint(s1 is s3)\n",[32,1110,1111,1121,1130,1142,1146,1184],{"__ignoreMap":30},[35,1112,1113,1116,1118],{"class":37,"line":38},[35,1114,1115],{"class":41},"s1 ",[35,1117,46],{"class":45},[35,1119,1120],{"class":192}," \"hello\"\n",[35,1122,1123,1126,1128],{"class":37,"line":53},[35,1124,1125],{"class":41},"s2 ",[35,1127,46],{"class":45},[35,1129,1120],{"class":192},[35,1131,1132,1134,1137,1139],{"class":37,"line":686},[35,1133,962],{"class":49},[35,1135,1136],{"class":41},"(s1 ",[35,1138,265],{"class":45},[35,1140,1141],{"class":41}," s2)\n",[35,1143,1144],{"class":37,"line":692},[35,1145,689],{"emptyLinePlaceholder":80},[35,1147,1148,1151,1153,1156,1159,1162,1164,1167,1169,1172,1174,1176,1178,1181],{"class":37,"line":977},[35,1149,1150],{"class":41},"s3 ",[35,1152,46],{"class":45},[35,1154,1155],{"class":192}," \"\"",[35,1157,1158],{"class":41},".join([",[35,1160,1161],{"class":192},"\"h\"",[35,1163,132],{"class":41},[35,1165,1166],{"class":192},"\"e\"",[35,1168,132],{"class":41},[35,1170,1171],{"class":192},"\"l\"",[35,1173,132],{"class":41},[35,1175,1171],{"class":192},[35,1177,132],{"class":41},[35,1179,1180],{"class":192},"\"o\"",[35,1182,1183],{"class":41},"])\n",[35,1185,1186,1188,1190,1192],{"class":37,"line":987},[35,1187,962],{"class":49},[35,1189,1136],{"class":41},[35,1191,265],{"class":45},[35,1193,1194],{"class":41}," s3)\n",[68,1196,1198,1204,1214,1225],{"className":1197},[71],[73,1199,1201,1203],{"className":1200},[76],[78,1202],{"disabled":80,"type":81}," All strings with equal content are always the same object, no matter how they are constructed",[73,1205,1207,1209,1210,1213],{"className":1206},[76],[78,1208],{"disabled":80,"type":81}," Compile-time string literals that look like identifiers are commonly interned and may share identity, but strings built at runtime (e.g. via concatenation or ",[32,1211,1212],{},"join",") are typically distinct objects even with identical content",[73,1215,1217,1219,1220,1222,1223],{"className":1216},[76],[78,1218],{"disabled":80,"type":81}," No strings are ever interned in CPython; ",[32,1221,265],{}," on strings is always ",[32,1224,415],{},[73,1226,1228,1230,1231],{"className":1227},[76],[78,1229],{"disabled":80,"type":81}," Interning applies only to numeric strings like ",[32,1232,1233],{},"\"123\"",[109,1235,1236,1238,1245],{},[112,1237,114],{},[116,1239,1240,1242,1243,1213],{},[119,1241,121],{}," B — Compile-time string literals that look like identifiers are commonly interned and may share identity, but strings built at runtime (e.g. via concatenation or ",[32,1244,1212],{},[116,1246,1247,331,1249,1252,1253,1256,1257,1259,1260,1263,1264,1267,1268,405,1271,1273,1274,1276,1277,1280,1281,1283,1284,1286],{},[119,1248,127],{},[119,1250,1251],{},"Debug"," — CPython, as an optimization, often interns short literals that resemble identifiers at compile time, so ",[32,1254,1255],{},"s1 is s2"," frequently prints ",[32,1258,408],{},". But ",[32,1261,1262],{},"s3",", built at runtime via ",[32,1265,1266],{},"\"\".join(...)",", is a freshly allocated string object even though it's equal in content, so ",[32,1269,1270],{},"s1 is s3",[32,1272,415],{},". This is a classic footgun: code that appears to work using ",[32,1275,265],{}," for string comparison in a quick test can silently break once the string is produced dynamically (e.g., from user input, formatting, or ",[32,1278,1279],{},"+"," concatenation). Always compare string values with ",[32,1282,268],{},", never ",[32,1285,265],{},".",[14,1288,1289,1293,1340,1393],{"language":16},[18,1290,1292],{"id":1291},"q10-what-does-the-following-print-and-why-is-it-surprising","Q10. What does the following print, and why is it surprising?",[23,1294,1295],{"language":16},[26,1296,1298],{"className":28,"code":1297,"language":16,"meta":30,"style":30},"n = float(\"nan\")\nprint(n == n)\nprint(n is n)\n",[32,1299,1300,1318,1330],{"__ignoreMap":30},[35,1301,1302,1305,1307,1310,1312,1315],{"class":37,"line":38},[35,1303,1304],{"class":41},"n ",[35,1306,46],{"class":45},[35,1308,1309],{"class":49}," float",[35,1311,675],{"class":41},[35,1313,1314],{"class":192},"\"nan\"",[35,1316,1317],{"class":41},")\n",[35,1319,1320,1322,1325,1327],{"class":37,"line":53},[35,1321,962],{"class":49},[35,1323,1324],{"class":41},"(n ",[35,1326,268],{"class":45},[35,1328,1329],{"class":41}," n)\n",[35,1331,1332,1334,1336,1338],{"class":37,"line":686},[35,1333,962],{"class":49},[35,1335,1324],{"class":41},[35,1337,265],{"class":45},[35,1339,1329],{"class":41},[68,1341,1343,1353,1373,1383],{"className":1342},[71],[73,1344,1346,331,1348,1018,1350,1352],{"className":1345},[76],[78,1347],{"disabled":80,"type":81},[32,1349,408],{},[32,1351,408],{}," — a value always equals itself",[73,1354,1356,331,1358,1018,1360,1362,1363,1365,1366,1368,1369,1372],{"className":1355},[76],[78,1357],{"disabled":80,"type":81},[32,1359,415],{},[32,1361,408],{}," — per IEEE 754, NaN never equals itself under ",[32,1364,268],{},", but ",[32,1367,265],{}," compares identity, and it's the same object bound to ",[32,1370,1371],{},"n"," both times",[73,1374,1376,331,1378,1018,1380,1382],{"className":1375},[76],[78,1377],{"disabled":80,"type":81},[32,1379,415],{},[32,1381,415],{}," — NaN breaks both identity and equality checks",[73,1384,1386,331,1388,1018,1390,1392],{"className":1385},[76],[78,1387],{"disabled":80,"type":81},[32,1389,408],{},[32,1391,415],{}," — NaN is equal to itself but Python creates a new object on each reference",[109,1394,1395,1397,1411],{},[112,1396,114],{},[116,1398,1399,378,1401,1018,1403,1362,1405,1365,1407,1368,1409,1372],{},[119,1400,121],{},[32,1402,415],{},[32,1404,408],{},[32,1406,268],{},[32,1408,265],{},[32,1410,1371],{},[116,1412,1413,331,1415,1417,1418,1421,1422,405,1425,1427,1428,405,1431,1433,1434,1436,1437,405,1440,1442,1443,1446,1447,1450,1451,1454],{},[119,1414,127],{},[119,1416,1251],{}," — ",[32,1419,1420],{},"NaN != NaN"," is mandated by the IEEE 754 floating-point standard (any comparison involving NaN except ",[32,1423,1424],{},"!=",[32,1426,415],{},"), so ",[32,1429,1430],{},"n == n",[32,1432,415],{}," even though ",[32,1435,1371],{}," is literally the same object as itself. ",[32,1438,1439],{},"n is n",[32,1441,408],{}," because identity doesn't care about the value-equality rules at all — it's trivially the same object. This is a real production gotcha: ",[32,1444,1445],{},"x == x"," is not a safe way to detect NaN; use ",[32,1448,1449],{},"math.isnan(x)"," instead, and remember ",[32,1452,1453],{},"NaN in some_list"," can silently fail to find a NaN it should logically match.",[14,1456,1457,1461,1499,1532],{"language":16},[18,1458,1460],{"id":1459},"q11-do-two-independently-created-empty-tuples-share-identity","Q11. Do two independently created empty tuples share identity?",[23,1462,1463],{"language":16},[26,1464,1466],{"className":28,"code":1465,"language":16,"meta":30,"style":30},"t1 = ()\nt2 = ()\nprint(t1 is t2)\n",[32,1467,1468,1478,1487],{"__ignoreMap":30},[35,1469,1470,1473,1475],{"class":37,"line":38},[35,1471,1472],{"class":41},"t1 ",[35,1474,46],{"class":45},[35,1476,1477],{"class":41}," ()\n",[35,1479,1480,1483,1485],{"class":37,"line":53},[35,1481,1482],{"class":41},"t2 ",[35,1484,46],{"class":45},[35,1486,1477],{"class":41},[35,1488,1489,1491,1494,1496],{"class":37,"line":686},[35,1490,962],{"class":49},[35,1492,1493],{"class":41},"(t1 ",[35,1495,265],{"class":45},[35,1497,1498],{"class":41}," t2)\n",[68,1500,1502,1508,1514,1520],{"className":1501},[71],[73,1503,1505,1507],{"className":1504},[76],[78,1506],{"disabled":80,"type":81}," No — every tuple literal, even an empty one, allocates a new object",[73,1509,1511,1513],{"className":1510},[76],[78,1512],{"disabled":80,"type":81}," Yes — CPython caches a singleton empty tuple, so both names typically refer to the same object",[73,1515,1517,1519],{"className":1516},[76],[78,1518],{"disabled":80,"type":81}," Only inside function bodies, never at module level",[73,1521,1523,1525,1526,1529,1530],{"className":1522},[76],[78,1524],{"disabled":80,"type":81}," Only if both are explicitly declared with ",[32,1527,1528],{},"tuple()"," instead of ",[32,1531,107],{},[109,1533,1534,1536,1541],{},[112,1535,114],{},[116,1537,1538,1540],{},[119,1539,121],{}," B — Yes — CPython caches a singleton empty tuple, so both names typically refer to the same object",[116,1542,1543,331,1545,1547,1548,405,1551,1553,1554,405,1557,1559,1560,1564,1565,1567],{},[119,1544,127],{},[119,1546,1070],{}," — because the empty tuple is immutable and has no meaningful internal state to diverge, CPython optimizes by reusing one singleton empty-tuple object everywhere, so ",[32,1549,1550],{},"t1 is t2",[32,1552,408],{},". This is a CPython implementation detail (not a language guarantee), unlike, say, empty lists, where ",[32,1555,1556],{},"[] is []",[32,1558,415],{}," because lists are mutable and must never be silently shared. The lesson generalizes: never write code whose correctness ",[1561,1562,1563],"em",{},"depends"," on such identity caching — use ",[32,1566,268],{}," for comparisons regardless.",[14,1569,1570,1574,1645,1693],{"language":16},[18,1571,1573],{"id":1572},"q12-a-function-receives-a-mutable-list-and-appends-to-it-but-also-reassigns-the-parameter-name-inside-the-function-what-does-the-caller-observe","Q12. A function receives a mutable list and appends to it, but also reassigns the parameter name inside the function. What does the caller observe?",[23,1575,1576],{"language":16},[26,1577,1579],{"className":28,"code":1578,"language":16,"meta":30,"style":30},"def process(items):\n    items.append(\"processed\")\n    items = [\"replaced\"]\n\ndata = [\"order-1\"]\nprocess(data)\nprint(data)\n",[32,1580,1581,1591,1601,1615,1619,1633,1638],{"__ignoreMap":30},[35,1582,1583,1585,1588],{"class":37,"line":38},[35,1584,56],{"class":45},[35,1586,1587],{"class":59}," process",[35,1589,1590],{"class":41},"(items):\n",[35,1592,1593,1596,1599],{"class":37,"line":53},[35,1594,1595],{"class":41},"    items.append(",[35,1597,1598],{"class":192},"\"processed\"",[35,1600,1317],{"class":41},[35,1602,1603,1606,1608,1610,1613],{"class":37,"line":686},[35,1604,1605],{"class":41},"    items ",[35,1607,46],{"class":45},[35,1609,285],{"class":41},[35,1611,1612],{"class":192},"\"replaced\"",[35,1614,301],{"class":41},[35,1616,1617],{"class":37,"line":692},[35,1618,689],{"emptyLinePlaceholder":80},[35,1620,1621,1624,1626,1628,1631],{"class":37,"line":977},[35,1622,1623],{"class":41},"data ",[35,1625,46],{"class":45},[35,1627,285],{"class":41},[35,1629,1630],{"class":192},"\"order-1\"",[35,1632,301],{"class":41},[35,1634,1635],{"class":37,"line":987},[35,1636,1637],{"class":41},"process(data)\n",[35,1639,1640,1642],{"class":37,"line":997},[35,1641,962],{"class":49},[35,1643,1644],{"class":41},"(data)\n",[68,1646,1648,1657,1676,1685],{"className":1647},[71],[73,1649,1651,331,1653,1656],{"className":1650},[76],[78,1652],{"disabled":80,"type":81},[32,1654,1655],{},"[\"replaced\"]"," — the reassignment inside the function propagates back to the caller",[73,1658,1660,331,1662,1665,1666,1668,1669,1672,1673],{"className":1659},[76],[78,1661],{"disabled":80,"type":81},[32,1663,1664],{},"[\"order-1\", \"processed\"]"," — the in-place ",[32,1667,603],{}," mutates the shared object the caller sees, but rebinding the local name ",[32,1670,1671],{},"items"," only affects the local scope, not the caller's ",[32,1674,1675],{},"data",[73,1677,1679,331,1681,1684],{"className":1678},[76],[78,1680],{"disabled":80,"type":81},[32,1682,1683],{},"[\"order-1\"]"," — function calls never affect the caller's objects",[73,1686,1688,202,1690,1692],{"className":1687},[76],[78,1689],{"disabled":80,"type":81},[32,1691,205],{},", because you cannot both mutate and reassign a parameter in the same function",[109,1694,1695,1697,1709],{},[112,1696,114],{},[116,1698,1699,378,1701,1665,1703,1668,1705,1672,1707],{},[119,1700,121],{},[32,1702,1664],{},[32,1704,603],{},[32,1706,1671],{},[32,1708,1675],{},[116,1710,1711,1713,1714,1717,1718,1721,1722,1724,1725,1727],{},[119,1712,127],{}," Python passes arguments by binding the parameter name to the same object the caller passed (\"pass by object reference\"). ",[32,1715,1716],{},"items.append(...)"," mutates that shared list, so the caller sees it. But ",[32,1719,1720],{},"items = [\"replaced\"]"," merely rebinds the local name ",[32,1723,1671],{}," to point at a brand-new list — it does not, and cannot, reach back and change what ",[32,1726,1675],{}," points to. Beginners often expect either \"everything propagates\" (A) or \"nothing propagates\" (C); the real behavior is a mix, and it's the single most common source of confusion around Python's argument-passing model. Option D describes a restriction that doesn't exist.",[14,1729,1730,1736,1794,1867],{"language":16},[18,1731,1733,1734,166],{"id":1732},"q13-what-does-the-following-print-and-what-does-it-reveal-about-bool","Q13. What does the following print, and what does it reveal about ",[32,1735,539],{},[23,1737,1738],{"language":16},[26,1739,1741],{"className":28,"code":1740,"language":16,"meta":30,"style":30},"print(True == 1)\nprint(isinstance(True, int))\nprint(True + True)\n",[32,1742,1743,1759,1778],{"__ignoreMap":30},[35,1744,1745,1747,1749,1751,1754,1757],{"class":37,"line":38},[35,1746,962],{"class":49},[35,1748,675],{"class":41},[35,1750,408],{"class":49},[35,1752,1753],{"class":45}," ==",[35,1755,1756],{"class":49}," 1",[35,1758,1317],{"class":41},[35,1760,1761,1763,1765,1767,1769,1771,1773,1775],{"class":37,"line":53},[35,1762,962],{"class":49},[35,1764,675],{"class":41},[35,1766,733],{"class":49},[35,1768,675],{"class":41},[35,1770,408],{"class":49},[35,1772,132],{"class":41},[35,1774,85],{"class":49},[35,1776,1777],{"class":41},"))\n",[35,1779,1780,1782,1784,1786,1789,1792],{"class":37,"line":686},[35,1781,962],{"class":49},[35,1783,675],{"class":41},[35,1785,408],{"class":49},[35,1787,1788],{"class":45}," +",[35,1790,1791],{"class":49}," True",[35,1793,1317],{"class":41},[68,1795,1797,1809,1838,1850],{"className":1796},[71],[73,1798,1800,331,1802,132,1804,132,1806,1808],{"className":1799},[76],[78,1801],{"disabled":80,"type":81},[32,1803,415],{},[32,1805,415],{},[32,1807,205],{}," — booleans are unrelated to integers",[73,1810,1812,331,1814,132,1816,132,1818,1417,1820,1822,1823,1825,1826,1828,1829,1831,1832,1828,1834,1837],{"className":1811},[76],[78,1813],{"disabled":80,"type":81},[32,1815,408],{},[32,1817,408],{},[32,1819,293],{},[32,1821,539],{}," is a subclass of ",[32,1824,85],{}," in Python, so ",[32,1827,408],{},"\u002F",[32,1830,415],{}," behave as ",[32,1833,288],{},[32,1835,1836],{},"0"," in arithmetic and comparisons",[73,1839,1841,331,1843,132,1845,132,1847,1849],{"className":1840},[76],[78,1842],{"disabled":80,"type":81},[32,1844,408],{},[32,1846,415],{},[32,1848,205],{}," — booleans equal integers by value but are not related by type",[73,1851,1853,331,1855,132,1857,132,1859,1417,1861,1863,1864,1866],{"className":1852},[76],[78,1854],{"disabled":80,"type":81},[32,1856,415],{},[32,1858,408],{},[32,1860,293],{},[32,1862,539],{}," inherits from ",[32,1865,85],{}," but the values are never equal",[109,1868,1869,1871,1893],{},[112,1870,114],{},[116,1872,1873,378,1875,132,1877,132,1879,1417,1881,1822,1883,1825,1885,1828,1887,1831,1889,1828,1891,1837],{},[119,1874,121],{},[32,1876,408],{},[32,1878,408],{},[32,1880,293],{},[32,1882,539],{},[32,1884,85],{},[32,1886,408],{},[32,1888,415],{},[32,1890,288],{},[32,1892,1836],{},[116,1894,1895,331,1897,1417,1899,1901,1902,1904,1905,139,1907,1909,1910,139,1912,1914,1915,405,1918,132,1920,405,1923,597,1925,1928,1929,1931,1932,1935,1936,597,1938,1941,1942,139,1945,1286],{},[119,1896,127],{},[119,1898,1251],{},[32,1900,539],{}," is literally a subclass of ",[32,1903,85],{},", with ",[32,1906,408],{},[32,1908,415],{}," behaving as ",[32,1911,288],{},[32,1913,1836],{}," respectively; that's why ",[32,1916,1917],{},"True == 1",[32,1919,408],{},[32,1921,1922],{},"isinstance(True, int)",[32,1924,408],{},[32,1926,1927],{},"True + True"," evaluates to ",[32,1930,293],{}," without error. This surprises people who assume booleans are a wholly separate type. It has real consequences: ",[32,1933,1934],{},"sum([True, False, True])"," yields ",[32,1937,293],{},[32,1939,1940],{},"{1: \"a\", True: \"b\"}"," collapses to a single key because ",[32,1943,1944],{},"1 == True",[32,1946,1947],{},"hash(1) == hash(True)",[14,1949,1950,1962,1998],{},[18,1951,1953,1954,1957,1958,1961],{"id":1952},"q14-is-it-safe-to-compare-idobj_a-idobj_b-for-two-objects-that-existed-at-different-non-overlapping-points-in-a-long-running-program-to-conclude-they-were-the-same-object","Q14. Is it safe to compare ",[32,1955,1956],{},"id(obj_a) == id(obj_b)"," for two objects that existed at ",[1561,1959,1960],{},"different, non-overlapping"," points in a long-running program to conclude they were \"the same object\"?",[68,1963,1965,1974,1983,1992],{"className":1964},[71],[73,1966,1968,1970,1971,1973],{"className":1967},[76],[78,1969],{"disabled":80,"type":81}," Yes, ",[32,1972,146],{}," values are globally unique for all time, so a match always proves it was the same object",[73,1975,1977,1979,1980,1982],{"className":1976},[76],[78,1978],{"disabled":80,"type":81}," No — once an object is garbage-collected, CPython may reuse its freed memory address for a completely unrelated new object, so a matching ",[32,1981,146],{}," across non-overlapping lifetimes proves nothing",[73,1984,1986,1988,1989,1991],{"className":1985},[76],[78,1987],{"disabled":80,"type":81}," No, because ",[32,1990,146],{}," is randomized on every call and never repeats",[73,1993,1995,1997],{"className":1994},[76],[78,1996],{"disabled":80,"type":81}," Yes, but only for immutable types",[109,1999,2000,2002,2009],{},[112,2001,114],{},[116,2003,2004,2006,2007,1982],{},[119,2005,121],{}," B — No — once an object is garbage-collected, CPython may reuse its freed memory address for a completely unrelated new object, so a matching ",[32,2008,146],{},[116,2010,2011,331,2013,1417,2016,2018,2019,2022,2023,2025,2026,2028],{},[119,2012,127],{},[119,2014,2015],{},"Safety",[32,2017,146],{}," uniqueness is only guaranteed among objects that are alive ",[1561,2020,2021],{},"at the same time","; CPython's allocator is free to hand a freshly freed address to a brand-new, unrelated object. A long-running service that logs ",[32,2024,146],{}," values to \"track\" objects across time can be misled into thinking two clearly different objects are the same one. The safe pattern is to keep a live reference (preventing garbage collection) for as long as identity needs to be checked, rather than persisting bare ",[32,2027,146],{}," integers.",[14,2030,2031,2042,2065,2100],{"language":16},[18,2032,2034,2035,2037,2038,2041],{"id":2033},"q15-what-is-the-idiomatic-way-to-check-whether-obj-is-an-instance-of-myclass-or-one-of-its-subclasses","Q15. What is the idiomatic way to check whether ",[32,2036,644],{}," is an instance of ",[32,2039,2040],{},"MyClass"," or one of its subclasses?",[23,2043,2044],{"language":16},[26,2045,2047],{"className":28,"code":2046,"language":16,"meta":30,"style":30},"if isinstance(obj, MyClass):\n    ...\n",[32,2048,2049,2060],{"__ignoreMap":30},[35,2050,2051,2054,2057],{"class":37,"line":38},[35,2052,2053],{"class":45},"if",[35,2055,2056],{"class":49}," isinstance",[35,2058,2059],{"class":41},"(obj, MyClass):\n",[35,2061,2062],{"class":37,"line":53},[35,2063,2064],{"class":49},"    ...\n",[68,2066,2068,2076,2084,2092],{"className":2067},[71],[73,2069,2071,331,2073],{"className":2070},[76],[78,2072],{"disabled":80,"type":81},[32,2074,2075],{},"if type(obj) == MyClass:",[73,2077,2079,331,2081],{"className":2078},[76],[78,2080],{"disabled":80,"type":81},[32,2082,2083],{},"if isinstance(obj, MyClass):",[73,2085,2087,331,2089],{"className":2086},[76],[78,2088],{"disabled":80,"type":81},[32,2090,2091],{},"if obj.__class__.__name__ == \"MyClass\":",[73,2093,2095,331,2097],{"className":2094},[76],[78,2096],{"disabled":80,"type":81},[32,2098,2099],{},"if str(type(obj)) == \"MyClass\":",[109,2101,2102,2104,2110],{},[112,2103,114],{},[116,2105,2106,378,2108],{},[119,2107,121],{},[32,2109,2083],{},[116,2111,2112,331,2114,1417,2117,2119,2120,2123],{},[119,2113,127],{},[119,2115,2116],{},"Idiom",[32,2118,733],{}," is the idiomatic, subclass-aware check and also gracefully supports checking against a tuple of types (",[32,2121,2122],{},"isinstance(obj, (int, float))","). Option A silently excludes legitimate subclass instances, which routinely breaks polymorphic code paths (e.g., custom exceptions or ORM model subclasses). Options C and D are fragile string-matching hacks that break under refactors, module renames, or subclassing, and are never the recommended approach.",[14,2125,2126,2133,2159,2194],{"language":16},[18,2127,2129,2130,166],{"id":2128},"q16-what-is-the-idiomatic-way-to-check-whether-a-variable-is-none","Q16. What is the idiomatic way to check whether a variable is ",[32,2131,2132],{},"None",[23,2134,2135],{"language":16},[26,2136,2138],{"className":28,"code":2137,"language":16,"meta":30,"style":30},"if value is None:\n    ...\n",[32,2139,2140,2155],{"__ignoreMap":30},[35,2141,2142,2144,2147,2149,2152],{"class":37,"line":38},[35,2143,2053],{"class":45},[35,2145,2146],{"class":41}," value ",[35,2148,265],{"class":45},[35,2150,2151],{"class":49}," None",[35,2153,2154],{"class":41},":\n",[35,2156,2157],{"class":37,"line":53},[35,2158,2064],{"class":49},[68,2160,2162,2170,2178,2186],{"className":2161},[71],[73,2163,2165,331,2167],{"className":2164},[76],[78,2166],{"disabled":80,"type":81},[32,2168,2169],{},"if value == None:",[73,2171,2173,331,2175],{"className":2172},[76],[78,2174],{"disabled":80,"type":81},[32,2176,2177],{},"if value is None:",[73,2179,2181,331,2183],{"className":2180},[76],[78,2182],{"disabled":80,"type":81},[32,2184,2185],{},"if not value:",[73,2187,2189,331,2191],{"className":2188},[76],[78,2190],{"disabled":80,"type":81},[32,2192,2193],{},"if value.__eq__(None):",[109,2195,2196,2198,2204],{},[112,2197,114],{},[116,2199,2200,378,2202],{},[119,2201,121],{},[32,2203,2177],{},[116,2205,2206,331,2208,1417,2210,2212,2213,1828,2215,1077,2218,2220,2221,2224,2225,2227,2228,2230,2231,2233,2234,2236,2237,132,2239,597,2242,2245],{},[119,2207,127],{},[119,2209,2116],{},[32,2211,2132],{}," is a singleton, so identity comparison is both correct and faster than an equality check, and PEP 8 explicitly recommends ",[32,2214,265],{},[32,2216,2217],{},"is not",[32,2219,2132],{}," comparisons. Option A technically often works too (since ",[32,2222,2223],{},"None.__eq__"," falls back to identity-like behavior for the default case), but it's non-idiomatic and, critically, an object could override ",[32,2226,351],{}," to claim it equals ",[32,2229,2132],{},", silently breaking an ",[32,2232,268],{}," check in a way ",[32,2235,265],{}," never can. Option C is a different, broader check — it also matches falsy values like ",[32,2238,1836],{},[32,2240,2241],{},"\"\"",[32,2243,2244],{},"[]",", which is a common and dangerous conflation with \"is None\". Option D is needlessly indirect and bypasses Python's reflected-comparison protocol.",[14,2247,2248,2257,2296],{},[18,2249,2251,2252,812,2254,2256],{"id":2250},"q17-should-application-logic-ever-rely-on-cpythons-small-integer-or-string-interning-caching-ie-using-is-where-is-meant","Q17. Should application logic ever rely on CPython's small-integer or string-interning caching (i.e., using ",[32,2253,265],{},[32,2255,268],{}," is meant)?",[68,2258,2260,2266,2279,2285],{"className":2259},[71],[73,2261,2263,2265],{"className":2262},[76],[78,2264],{"disabled":80,"type":81}," Yes — it's a documented, guaranteed language feature safe to depend on",[73,2267,2269,2271,2272,2275,2276,2278],{"className":2268},[76],[78,2270],{"disabled":80,"type":81}," No — it is a CPython implementation detail that can change between versions\u002Fimplementations (e.g., PyPy) and even between contexts (interactive shell vs. module vs. ",[32,2273,2274],{},"-O"," optimizations); use ",[32,2277,268],{}," for value comparisons",[73,2280,2282,2284],{"className":2281},[76],[78,2283],{"disabled":80,"type":81}," Yes, but only for integers, never for strings",[73,2286,2288,2290,2291,139,2293,2295],{"className":2287},[76],[78,2289],{"disabled":80,"type":81}," It doesn't matter, since ",[32,2292,265],{},[32,2294,268],{}," always agree for built-in immutable types",[109,2297,2298,2300,2309],{},[112,2299,114],{},[116,2301,2302,2304,2305,2275,2307,2278],{},[119,2303,121],{}," B — No — it is a CPython implementation detail that can change between versions\u002Fimplementations (e.g., PyPy) and even between contexts (interactive shell vs. module vs. ",[32,2306,2274],{},[32,2308,268],{},[116,2310,2311,331,2313,2316,2317,2320,2321,2323,2324,2327,2328,139,2330,2332],{},[119,2312,127],{},[119,2314,2315],{},"Portability"," — small-int caching and string interning are documented as CPython optimizations, not language guarantees; other implementations (PyPy, Jython) or even future CPython releases are free to cache differently, or not at all. Code that happens to pass tests because ",[32,2318,2319],{},"100 is 100"," was ",[32,2322,408],{}," can fail unpredictably in a different environment or with slightly larger numbers. Option D is directly contradicted by the ",[32,2325,2326],{},"x = 1000; y = 1000"," example seen earlier in this quiz, where ",[32,2329,265],{},[32,2331,268],{}," diverge.",[14,2334,2335,2341,2384,2423],{"language":16},[18,2336,2338,2339,166],{"id":2337},"q18-which-of-the-following-can-be-used-as-a-key-in-a-dict","Q18. Which of the following can be used as a key in a ",[32,2340,510],{},[23,2342,2343],{"language":16},[26,2344,2346],{"className":28,"code":2345,"language":16,"meta":30,"style":30},"config = {\n    (\"region\", \"us-east-1\"): \"primary\",\n}\n",[32,2347,2348,2358,2379],{"__ignoreMap":30},[35,2349,2350,2353,2355],{"class":37,"line":38},[35,2351,2352],{"class":41},"config ",[35,2354,46],{"class":45},[35,2356,2357],{"class":41}," {\n",[35,2359,2360,2363,2366,2368,2371,2373,2376],{"class":37,"line":53},[35,2361,2362],{"class":41},"    (",[35,2364,2365],{"class":192},"\"region\"",[35,2367,132],{"class":41},[35,2369,2370],{"class":192},"\"us-east-1\"",[35,2372,681],{"class":41},[35,2374,2375],{"class":192},"\"primary\"",[35,2377,2378],{"class":41},",\n",[35,2380,2381],{"class":37,"line":686},[35,2382,2383],{"class":41},"}\n",[68,2385,2387,2395,2407,2415],{"className":2386},[71],[73,2388,2390,202,2392,2394],{"className":2389},[76],[78,2391],{"disabled":80,"type":81},[32,2393,507],{},", since dict keys can be any object",[73,2396,2398,202,2400,2402,2403,2406],{"className":2397},[76],[78,2399],{"disabled":80,"type":81},[32,2401,503],{}," of hashable elements, like ",[32,2404,2405],{},"(\"region\", \"us-east-1\")",", since it is immutable and hashable",[73,2408,2410,202,2412,2414],{"className":2409},[76],[78,2411],{"disabled":80,"type":81},[32,2413,510],{},", since nesting dictionaries is common",[73,2416,2418,202,2420,2422],{"className":2417},[76],[78,2419],{"disabled":80,"type":81},[32,2421,513],{},", since sets are also collections",[109,2424,2425,2427,2436],{},[112,2426,114],{},[116,2428,2429,2431,2432,2402,2434,2406],{},[119,2430,121],{}," B — A ",[32,2433,503],{},[32,2435,2405],{},[116,2437,2438,2440,2441,2444,2445,2447,2448,132,2450,597,2452,2454,2455,2458],{},[119,2439,127],{}," Dict keys must be hashable, which in practice means immutable (or at least implementing a stable ",[32,2442,2443],{},"__hash__","); a ",[32,2446,503],{}," of hashable elements qualifies and is a common composite-key pattern. ",[32,2449,507],{},[32,2451,510],{},[32,2453,513],{}," are all mutable and unhashable by default, so using any of them as a key raises ",[32,2456,2457],{},"TypeError: unhashable type",". This ties directly back to mutability: a hash must stay constant for an object's lifetime, and a mutable object's contents — and thus its \"natural\" hash — could change after insertion, which would corrupt the hash table.",[14,2460,2461,2471,2534,2588],{"language":16},[18,2462,2464,2465,2468,2469,166],{"id":2463},"q19-what-is-the-correct-defensive-way-to-convert-untrusted-user-input-like-abc-to-an-int","Q19. What is the correct, defensive way to convert untrusted user input like ",[32,2466,2467],{},"\"abc\""," to an ",[32,2470,85],{},[23,2472,2473],{"language":16},[26,2474,2476],{"className":28,"code":2475,"language":16,"meta":30,"style":30},"raw = input(\"Enter age: \")\ntry:\n    age = int(raw)\nexcept ValueError:\n    age = None\n",[32,2477,2478,2495,2502,2515,2525],{"__ignoreMap":30},[35,2479,2480,2483,2485,2488,2490,2493],{"class":37,"line":38},[35,2481,2482],{"class":41},"raw ",[35,2484,46],{"class":45},[35,2486,2487],{"class":49}," input",[35,2489,675],{"class":41},[35,2491,2492],{"class":192},"\"Enter age: \"",[35,2494,1317],{"class":41},[35,2496,2497,2500],{"class":37,"line":53},[35,2498,2499],{"class":45},"try",[35,2501,2154],{"class":41},[35,2503,2504,2507,2509,2512],{"class":37,"line":686},[35,2505,2506],{"class":41},"    age ",[35,2508,46],{"class":45},[35,2510,2511],{"class":49}," int",[35,2513,2514],{"class":41},"(raw)\n",[35,2516,2517,2520,2523],{"class":37,"line":692},[35,2518,2519],{"class":45},"except",[35,2521,2522],{"class":49}," ValueError",[35,2524,2154],{"class":41},[35,2526,2527,2529,2531],{"class":37,"line":977},[35,2528,2506],{"class":41},[35,2530,46],{"class":45},[35,2532,2533],{"class":49}," None\n",[68,2535,2537,2547,2565,2575],{"className":2536},[71],[73,2538,2540,2542,2543,2546],{"className":2539},[76],[78,2541],{"disabled":80,"type":81}," Call ",[32,2544,2545],{},"int(raw)"," directly and trust it will always succeed",[73,2548,2550,2552,2553,2556,2557,2560,2561,2564],{"className":2549},[76],[78,2551],{"disabled":80,"type":81}," Wrap the conversion in ",[32,2554,2555],{},"try\u002Fexcept ValueError"," (as shown), since ",[32,2558,2559],{},"int()"," raises ",[32,2562,2563],{},"ValueError"," on non-numeric strings rather than returning a sentinel",[73,2566,2568,2570,2571,2574],{"className":2567},[76],[78,2569],{"disabled":80,"type":81}," Use ",[32,2572,2573],{},"float(raw)"," instead, since it never raises exceptions",[73,2576,2578,2580,2581,2584,2585,2587],{"className":2577},[76],[78,2579],{"disabled":80,"type":81}," Check ",[32,2582,2583],{},"raw.isdigit()"," only, since that alone guarantees ",[32,2586,2559],{}," will succeed for any valid integer, including negatives",[109,2589,2590,2592,2603],{},[112,2591,114],{},[116,2593,2594,2596,2597,2556,2599,2560,2601,2564],{},[119,2595,121],{}," B — Wrap the conversion in ",[32,2598,2555],{},[32,2600,2559],{},[32,2602,2563],{},[116,2604,2605,331,2607,2609,2610,2613,2614,2616,2617,2619,2620,2622,2623,2625,2626,2560,2628,2630,2631,2634,2635,2638,2639,2641,2642,2645,2646,405,2649,2651,2652,2655],{},[119,2606,127],{},[32,2608,2559],{}," (and ",[32,2611,2612],{},"float()",") raise ",[32,2615,2563],{}," for unparseable strings instead of returning ",[32,2618,2132],{}," or ",[32,2621,1836],{},", so unguarded conversion of external input is a production crash waiting to happen — catching ",[32,2624,2563],{}," is the correct handling. Option A ignores that risk entirely. Option C is wrong on its face — ",[32,2627,2612],{},[32,2629,2563],{}," too (e.g., ",[32,2632,2633],{},"float(\"abc\")","). Option D is a subtle trap: ",[32,2636,2637],{},"str.isdigit()"," returns ",[32,2640,415],{}," for a leading ",[32,2643,2644],{},"-"," sign (",[32,2647,2648],{},"\"-5\".isdigit()",[32,2650,415],{},"), so relying on it alone would reject legitimate negative integers even though ",[32,2653,2654],{},"int(\"-5\")"," succeeds fine.",[14,2657,2658,2670,2732,2777],{"language":16},[18,2659,2661,2662,2665,2666,2669],{"id":2660},"q20-two-engineers-are-debugging-why-mutating-settings_copy-also-changed-settings-elsewhere-in-a-large-codebase-what-is-the-most-likely-root-cause","Q20. Two engineers are debugging why mutating ",[32,2663,2664],{},"settings_copy"," also changed ",[32,2667,2668],{},"settings"," elsewhere in a large codebase. What is the most likely root cause?",[23,2671,2672],{"language":16},[26,2673,2675],{"className":28,"code":2674,"language":16,"meta":30,"style":30},"settings = {\"debug\": False}\nsettings_copy = settings\nsettings_copy[\"debug\"] = True\nprint(settings[\"debug\"])\n",[32,2676,2677,2696,2706,2721],{"__ignoreMap":30},[35,2678,2679,2682,2684,2687,2690,2692,2694],{"class":37,"line":38},[35,2680,2681],{"class":41},"settings ",[35,2683,46],{"class":45},[35,2685,2686],{"class":41}," {",[35,2688,2689],{"class":192},"\"debug\"",[35,2691,663],{"class":41},[35,2693,415],{"class":49},[35,2695,2383],{"class":41},[35,2697,2698,2701,2703],{"class":37,"line":53},[35,2699,2700],{"class":41},"settings_copy ",[35,2702,46],{"class":45},[35,2704,2705],{"class":41}," settings\n",[35,2707,2708,2711,2713,2716,2718],{"class":37,"line":686},[35,2709,2710],{"class":41},"settings_copy[",[35,2712,2689],{"class":192},[35,2714,2715],{"class":41},"] ",[35,2717,46],{"class":45},[35,2719,2720],{"class":49}," True\n",[35,2722,2723,2725,2728,2730],{"class":37,"line":692},[35,2724,962],{"class":49},[35,2726,2727],{"class":41},"(settings[",[35,2729,2689],{"class":192},[35,2731,1183],{"class":41},[68,2733,2735,2744,2763,2771],{"className":2734},[71],[73,2736,2738,331,2740,2743],{"className":2737},[76],[78,2739],{"disabled":80,"type":81},[32,2741,2742],{},"settings_copy = settings"," silently created a deep copy, and the bug lies elsewhere",[73,2745,2747,331,2749,2751,2752,132,2755,2758,2759,2762],{"className":2746},[76],[78,2748],{"disabled":80,"type":81},[32,2750,2742],{}," only creates a new alias to the same dict object — no copy was ever made, so mutating one mutates both; a real copy requires ",[32,2753,2754],{},"dict(settings)",[32,2756,2757],{},"settings.copy()",", or ",[32,2760,2761],{},"copy.deepcopy(settings)"," for nested structures",[73,2764,2766,331,2768,2770],{"className":2765},[76],[78,2767],{"disabled":80,"type":81},[32,2769,510],{}," objects are immutable, so this code should have raised an exception",[73,2772,2774,2776],{"className":2773},[76],[78,2775],{"disabled":80,"type":81}," This is a garbage collector bug and cannot be fixed in user code",[109,2778,2779,2781,2793],{},[112,2780,114],{},[116,2782,2783,378,2785,2751,2787,132,2789,2758,2791,2762],{},[119,2784,121],{},[32,2786,2742],{},[32,2788,2754],{},[32,2790,2757],{},[32,2792,2761],{},[116,2794,2795,331,2797,2799,2800,2802,2803,2805,2806,2808,2809,2812,2813,2815,2816,2818],{},[119,2796,127],{},[119,2798,2116],{}," — this is the single most common real-world \"why did my data change on its own\" bug: plain ",[32,2801,46],{}," never copies a mutable object, it only adds another name pointing at the same one. The fix is to explicitly request a copy — a shallow copy (",[32,2804,2754],{}," \u002F ",[32,2807,2757],{},") is enough for a flat dict of immutable values, while nested mutable structures need ",[32,2810,2811],{},"copy.deepcopy",". Option A describes behavior ",[32,2814,46],{}," simply does not have. Option C is false — ",[32,2817,510],{}," is mutable by design. Option D misattributes an application-level aliasing bug to the garbage collector, which is unrelated.",[2820,2821,2822],"style",{},"html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}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 .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}",{"title":30,"searchDepth":53,"depth":53,"links":2824},[2825,2826,2828,2830,2832,2833,2835,2837,2838,2839,2840,2841,2842,2844,2846,2848,2850,2852,2854,2856],{"id":20,"depth":686,"text":21},{"id":158,"depth":686,"text":2827},"Q2. What happens when a name already bound to an int is reassigned to a str?",{"id":261,"depth":686,"text":2829},"Q3. What is the core difference between is and ==?",{"id":426,"depth":686,"text":2831},"Q4. What does the built-in id() function return?",{"id":486,"depth":686,"text":487},{"id":633,"depth":686,"text":2834},"Q6. What is the difference between type(obj) == SomeClass and isinstance(obj, SomeClass) when obj might be an instance of a subclass?",{"id":807,"depth":686,"text":2836},"Q7. What happens when you execute b = a where a is a list?",{"id":932,"depth":686,"text":933},{"id":1102,"depth":686,"text":1103},{"id":1291,"depth":686,"text":1292},{"id":1459,"depth":686,"text":1460},{"id":1572,"depth":686,"text":1573},{"id":1732,"depth":686,"text":2843},"Q13. What does the following print, and what does it reveal about bool?",{"id":1952,"depth":686,"text":2845},"Q14. Is it safe to compare id(obj_a) == id(obj_b) for two objects that existed at different, non-overlapping points in a long-running program to conclude they were \"the same object\"?",{"id":2033,"depth":686,"text":2847},"Q15. What is the idiomatic way to check whether obj is an instance of MyClass or one of its subclasses?",{"id":2128,"depth":686,"text":2849},"Q16. What is the idiomatic way to check whether a variable is None?",{"id":2250,"depth":686,"text":2851},"Q17. Should application logic ever rely on CPython's small-integer or string-interning caching (i.e., using is where == is meant)?",{"id":2337,"depth":686,"text":2853},"Q18. Which of the following can be used as a key in a dict?",{"id":2463,"depth":686,"text":2855},"Q19. What is the correct, defensive way to convert untrusted user input like \"abc\" to an int?",{"id":2660,"depth":686,"text":2857},"Q20. Two engineers are debugging why mutating settings_copy also changed settings elsewhere in a large codebase. What is the most likely root cause?","md",{},"\u002Fpython\u002F02-variables-and-data-types",{"title":5,"description":30},"python\u002F02-variables-and-data-types","FolA5sswrjI0chDBgpu-qNnDTbTFI9OQloHc6wBjo3c",1787335397338]