[{"data":1,"prerenderedAt":1246},["ShallowReactive",2],{"blog-\u002Fblog\u002Fpython-is-vs-equals-equality-vs-identity":3},{"id":4,"title":5,"body":6,"description":1233,"difficulty":1234,"extension":1235,"framework":1236,"frameworkSlug":193,"meta":1237,"navigation":257,"order":261,"path":1238,"qaPath":1213,"seo":1239,"stem":1240,"subtopic":1241,"topic":1242,"topicSlug":1243,"updated":1244,"__hash__":1245},"blog\u002Fblog\u002Fpython-is-vs-equals-equality-vs-identity.md","Python == vs is — Equality vs Identity and the Interning Trap",{"type":7,"value":8,"toc":1219},"minimark",[9,14,38,42,173,180,188,305,311,385,390,406,511,518,527,684,694,700,709,887,895,989,993,1014,1032,1167,1171,1205,1215],[10,11,13],"h2",{"id":12},"two-questions-that-look-the-same-but-arent","Two questions that look the same but aren't",[15,16,17,18,22,23,26,27,30,31,34,35,37],"p",{},"Every Python developer eventually writes ",[19,20,21],"code",{},"if x is \"something\""," or ",[19,24,25],{},"if count is 0"," and\nis surprised when it sometimes works and sometimes doesn't. The root cause is that ",[19,28,29],{},"==","\nand ",[19,32,33],{},"is"," ask completely different questions — and CPython's internal optimisations quietly\nmake ",[19,36,33],{}," appear correct on certain values, hiding the real distinction until production.",[10,39,41],{"id":40},"quick-reference-comparison","Quick-reference comparison",[43,44,45,64],"table",{},[46,47,48],"thead",{},[49,50,51,54,59],"tr",{},[52,53],"th",{},[52,55,56,58],{},[19,57,29],{}," (equality)",[52,60,61,63],{},[19,62,33],{}," (identity)",[65,66,67,82,102,120,136,152],"tbody",{},[49,68,69,76,79],{},[70,71,72],"td",{},[73,74,75],"strong",{},"Question asked",[70,77,78],{},"\"Do these have the same value?\"",[70,80,81],{},"\"Are these the exact same object in memory?\"",[49,83,84,89,95],{},[70,85,86],{},[73,87,88],{},"Calls",[70,90,91,94],{},[19,92,93],{},"__eq__"," on the left operand",[70,96,97,98,101],{},"Compares ",[19,99,100],{},"id()"," — no method call",[49,103,104,109,114],{},[70,105,106],{},[73,107,108],{},"Two equal objects",[70,110,111],{},[19,112,113],{},"True",[70,115,116,119],{},[19,117,118],{},"False"," (usually)",[49,121,122,127,131],{},[70,123,124],{},[73,125,126],{},"Same object",[70,128,129],{},[19,130,113],{},[70,132,133,135],{},[19,134,113],{}," (always)",[49,137,138,143,149],{},[70,139,140],{},[73,141,142],{},"Can be overridden?",[70,144,145,146,148],{},"Yes — ",[19,147,93],{}," can return anything",[70,150,151],{},"No — pure identity, unoverridable",[49,153,154,159,162],{},[70,155,156],{},[73,157,158],{},"Use for",[70,160,161],{},"Values, data, content",[70,163,164,167,168,167,170,172],{},[19,165,166],{},"None",", ",[19,169,113],{},[19,171,118],{},", sentinels",[10,174,176,177,179],{"id":175},"what-does","What ",[19,178,29],{}," does",[15,181,182,184,185,187],{},[19,183,29],{}," calls ",[19,186,93],{}," on the left operand. The object decides what \"equal\" means. Two\ncompletely separate objects with the same content compare as equal:",[189,190,195],"pre",{"className":191,"code":192,"language":193,"meta":194,"style":194},"language-python shiki shiki-themes github-light github-dark","a = [1, 2, 3]\nb = [1, 2, 3]\n\na == b      # True  — same contents\na is b      # False — two different objects in memory\nid(a) == id(b)   # False — different addresses\n","python","",[19,196,197,230,252,259,273,285],{"__ignoreMap":194},[198,199,202,206,210,213,217,219,222,224,227],"span",{"class":200,"line":201},"line",1,[198,203,205],{"class":204},"sVt8B","a ",[198,207,209],{"class":208},"szBVR","=",[198,211,212],{"class":204}," [",[198,214,216],{"class":215},"sj4cs","1",[198,218,167],{"class":204},[198,220,221],{"class":215},"2",[198,223,167],{"class":204},[198,225,226],{"class":215},"3",[198,228,229],{"class":204},"]\n",[198,231,233,236,238,240,242,244,246,248,250],{"class":200,"line":232},2,[198,234,235],{"class":204},"b ",[198,237,209],{"class":208},[198,239,212],{"class":204},[198,241,216],{"class":215},[198,243,167],{"class":204},[198,245,221],{"class":215},[198,247,167],{"class":204},[198,249,226],{"class":215},[198,251,229],{"class":204},[198,253,255],{"class":200,"line":254},3,[198,256,258],{"emptyLinePlaceholder":257},true,"\n",[198,260,262,264,266,269],{"class":200,"line":261},4,[198,263,205],{"class":204},[198,265,29],{"class":208},[198,267,268],{"class":204}," b      ",[198,270,272],{"class":271},"sJ8bj","# True  — same contents\n",[198,274,276,278,280,282],{"class":200,"line":275},5,[198,277,205],{"class":204},[198,279,33],{"class":208},[198,281,268],{"class":204},[198,283,284],{"class":271},"# False — two different objects in memory\n",[198,286,288,291,294,296,299,302],{"class":200,"line":287},6,[198,289,290],{"class":215},"id",[198,292,293],{"class":204},"(a) ",[198,295,29],{"class":208},[198,297,298],{"class":215}," id",[198,300,301],{"class":204},"(b)   ",[198,303,304],{"class":271},"# False — different addresses\n",[15,306,307,308,310],{},"Because ",[19,309,93],{}," is a method, it can be overridden to return anything — including lying:",[189,312,314],{"className":191,"code":313,"language":193,"meta":194,"style":194},"class Trickster:\n    def __eq__(self, other): return True   # always \"equal\"\n\nt = Trickster()\nt == None      # True  — misleading!\nt is None      # False — identity can't be fooled\n",[19,315,316,328,348,352,362,374],{"__ignoreMap":194},[198,317,318,321,325],{"class":200,"line":201},[198,319,320],{"class":208},"class",[198,322,324],{"class":323},"sScJk"," Trickster",[198,326,327],{"class":204},":\n",[198,329,330,333,336,339,342,345],{"class":200,"line":232},[198,331,332],{"class":208},"    def",[198,334,335],{"class":215}," __eq__",[198,337,338],{"class":204},"(self, other): ",[198,340,341],{"class":208},"return",[198,343,344],{"class":215}," True",[198,346,347],{"class":271},"   # always \"equal\"\n",[198,349,350],{"class":200,"line":254},[198,351,258],{"emptyLinePlaceholder":257},[198,353,354,357,359],{"class":200,"line":261},[198,355,356],{"class":204},"t ",[198,358,209],{"class":208},[198,360,361],{"class":204}," Trickster()\n",[198,363,364,366,368,371],{"class":200,"line":275},[198,365,356],{"class":204},[198,367,29],{"class":208},[198,369,370],{"class":215}," None",[198,372,373],{"class":271},"      # True  — misleading!\n",[198,375,376,378,380,382],{"class":200,"line":287},[198,377,356],{"class":204},[198,379,33],{"class":208},[198,381,370],{"class":215},[198,383,384],{"class":271},"      # False — identity can't be fooled\n",[10,386,176,388,179],{"id":387},"what-is-does",[19,389,33],{},[15,391,392,394,395,398,399,402,403,405],{},[19,393,33],{}," compares object ",[73,396,397],{},"identity"," — specifically ",[19,400,401],{},"id(a) == id(b)",". In CPython, ",[19,404,100],{}," is\nthe memory address. Two names refer to the same object if and only if they point at the\nsame address.",[189,407,409],{"className":191,"code":408,"language":193,"meta":194,"style":194},"a = [1, 2, 3]\nb = a          # b is an alias for a, not a copy\n\nb is a         # True  — same object\nb == a         # True  — same contents too\n\nc = a[:]       # shallow copy — new object\nc is a         # False — new list\nc == a         # True  — same contents\n",[19,410,411,431,443,447,459,470,474,488,500],{"__ignoreMap":194},[198,412,413,415,417,419,421,423,425,427,429],{"class":200,"line":201},[198,414,205],{"class":204},[198,416,209],{"class":208},[198,418,212],{"class":204},[198,420,216],{"class":215},[198,422,167],{"class":204},[198,424,221],{"class":215},[198,426,167],{"class":204},[198,428,226],{"class":215},[198,430,229],{"class":204},[198,432,433,435,437,440],{"class":200,"line":232},[198,434,235],{"class":204},[198,436,209],{"class":208},[198,438,439],{"class":204}," a          ",[198,441,442],{"class":271},"# b is an alias for a, not a copy\n",[198,444,445],{"class":200,"line":254},[198,446,258],{"emptyLinePlaceholder":257},[198,448,449,451,453,456],{"class":200,"line":261},[198,450,235],{"class":204},[198,452,33],{"class":208},[198,454,455],{"class":204}," a         ",[198,457,458],{"class":271},"# True  — same object\n",[198,460,461,463,465,467],{"class":200,"line":275},[198,462,235],{"class":204},[198,464,29],{"class":208},[198,466,455],{"class":204},[198,468,469],{"class":271},"# True  — same contents too\n",[198,471,472],{"class":200,"line":287},[198,473,258],{"emptyLinePlaceholder":257},[198,475,477,480,482,485],{"class":200,"line":476},7,[198,478,479],{"class":204},"c ",[198,481,209],{"class":208},[198,483,484],{"class":204}," a[:]       ",[198,486,487],{"class":271},"# shallow copy — new object\n",[198,489,491,493,495,497],{"class":200,"line":490},8,[198,492,479],{"class":204},[198,494,33],{"class":208},[198,496,455],{"class":204},[198,498,499],{"class":271},"# False — new list\n",[198,501,503,505,507,509],{"class":200,"line":502},9,[198,504,479],{"class":204},[198,506,29],{"class":208},[198,508,455],{"class":204},[198,510,272],{"class":271},[10,512,514,515,517],{"id":513},"the-interning-trap-when-is-appears-to-work-on-values","The interning trap — when ",[19,516,33],{}," appears to work on values",[15,519,520,521,523,524,526],{},"CPython pre-creates singleton objects for performance. This makes ",[19,522,33],{}," return ",[19,525,113],{}," on\ncertain values even when comparing two separate \"literals\" — a dangerous coincidence that\nbreaks outside the cached range:",[189,528,530],{"className":191,"code":529,"language":193,"meta":194,"style":194},"# Small integers (-5 to 256) are cached singletons\na = 100; b = 100\na is b          # True  — same cached object (lucky!)\n\na = 300; b = 300\na is b          # False — outside the cache, two objects\n\n# Short identifier-like strings are auto-interned\nx = \"hello\"; y = \"hello\"\nx is y          # True  — auto-interned (lucky!)\n\nx = \"hello world!\"; y = \"hello world!\"\nx is y          # often False — not auto-interned\nx == y          # True  — always the correct comparison\n",[19,531,532,537,554,566,570,586,597,601,606,625,638,643,660,672],{"__ignoreMap":194},[198,533,534],{"class":200,"line":201},[198,535,536],{"class":271},"# Small integers (-5 to 256) are cached singletons\n",[198,538,539,541,543,546,549,551],{"class":200,"line":232},[198,540,205],{"class":204},[198,542,209],{"class":208},[198,544,545],{"class":215}," 100",[198,547,548],{"class":204},"; b ",[198,550,209],{"class":208},[198,552,553],{"class":215}," 100\n",[198,555,556,558,560,563],{"class":200,"line":254},[198,557,205],{"class":204},[198,559,33],{"class":208},[198,561,562],{"class":204}," b          ",[198,564,565],{"class":271},"# True  — same cached object (lucky!)\n",[198,567,568],{"class":200,"line":261},[198,569,258],{"emptyLinePlaceholder":257},[198,571,572,574,576,579,581,583],{"class":200,"line":275},[198,573,205],{"class":204},[198,575,209],{"class":208},[198,577,578],{"class":215}," 300",[198,580,548],{"class":204},[198,582,209],{"class":208},[198,584,585],{"class":215}," 300\n",[198,587,588,590,592,594],{"class":200,"line":287},[198,589,205],{"class":204},[198,591,33],{"class":208},[198,593,562],{"class":204},[198,595,596],{"class":271},"# False — outside the cache, two objects\n",[198,598,599],{"class":200,"line":476},[198,600,258],{"emptyLinePlaceholder":257},[198,602,603],{"class":200,"line":490},[198,604,605],{"class":271},"# Short identifier-like strings are auto-interned\n",[198,607,608,611,613,617,620,622],{"class":200,"line":502},[198,609,610],{"class":204},"x ",[198,612,209],{"class":208},[198,614,616],{"class":615},"sZZnC"," \"hello\"",[198,618,619],{"class":204},"; y ",[198,621,209],{"class":208},[198,623,624],{"class":615}," \"hello\"\n",[198,626,628,630,632,635],{"class":200,"line":627},10,[198,629,610],{"class":204},[198,631,33],{"class":208},[198,633,634],{"class":204}," y          ",[198,636,637],{"class":271},"# True  — auto-interned (lucky!)\n",[198,639,641],{"class":200,"line":640},11,[198,642,258],{"emptyLinePlaceholder":257},[198,644,646,648,650,653,655,657],{"class":200,"line":645},12,[198,647,610],{"class":204},[198,649,209],{"class":208},[198,651,652],{"class":615}," \"hello world!\"",[198,654,619],{"class":204},[198,656,209],{"class":208},[198,658,659],{"class":615}," \"hello world!\"\n",[198,661,663,665,667,669],{"class":200,"line":662},13,[198,664,610],{"class":204},[198,666,33],{"class":208},[198,668,634],{"class":204},[198,670,671],{"class":271},"# often False — not auto-interned\n",[198,673,675,677,679,681],{"class":200,"line":674},14,[198,676,610],{"class":204},[198,678,29],{"class":208},[198,680,634],{"class":204},[198,682,683],{"class":271},"# True  — always the correct comparison\n",[15,685,686,689,690,693],{},[73,687,688],{},"Why this is dangerous:"," code with ",[19,691,692],{},"is 100"," passes all tests (small values) and silently\nbreaks in production with larger inputs.",[10,695,697,698],{"id":696},"the-correct-uses-of-is","The correct uses of ",[19,699,33],{},[15,701,702,704,705,708],{},[19,703,33],{}," is correct exactly when you're checking against a ",[73,706,707],{},"true singleton"," — an object of\nwhich only one instance can ever exist:",[189,710,712],{"className":191,"code":711,"language":193,"meta":194,"style":194},"# None is a singleton — is is idiomatic and unambiguous\nif result is None:\n    ...\n\n# PEP 8 mandates is\u002Fis not for None and the bool singletons\nif flag is True:    # rarely needed — usually just `if flag:`\n    ...\nif flag is not False:\n    ...\n\n# Custom sentinels — identity is the whole point\n_MISSING = object()\n\ndef get(mapping, key, default=_MISSING):\n    value = mapping.get(key, _MISSING)\n    if value is _MISSING:   # distinguishes \"key absent\" from \"value is None\"\n        return default\n    return value\n",[19,713,714,719,733,738,742,747,764,768,784,788,792,797,811,815,833,849,869,878],{"__ignoreMap":194},[198,715,716],{"class":200,"line":201},[198,717,718],{"class":271},"# None is a singleton — is is idiomatic and unambiguous\n",[198,720,721,724,727,729,731],{"class":200,"line":232},[198,722,723],{"class":208},"if",[198,725,726],{"class":204}," result ",[198,728,33],{"class":208},[198,730,370],{"class":215},[198,732,327],{"class":204},[198,734,735],{"class":200,"line":254},[198,736,737],{"class":215},"    ...\n",[198,739,740],{"class":200,"line":261},[198,741,258],{"emptyLinePlaceholder":257},[198,743,744],{"class":200,"line":275},[198,745,746],{"class":271},"# PEP 8 mandates is\u002Fis not for None and the bool singletons\n",[198,748,749,751,754,756,758,761],{"class":200,"line":287},[198,750,723],{"class":208},[198,752,753],{"class":204}," flag ",[198,755,33],{"class":208},[198,757,344],{"class":215},[198,759,760],{"class":204},":    ",[198,762,763],{"class":271},"# rarely needed — usually just `if flag:`\n",[198,765,766],{"class":200,"line":476},[198,767,737],{"class":215},[198,769,770,772,774,776,779,782],{"class":200,"line":490},[198,771,723],{"class":208},[198,773,753],{"class":204},[198,775,33],{"class":208},[198,777,778],{"class":208}," not",[198,780,781],{"class":215}," False",[198,783,327],{"class":204},[198,785,786],{"class":200,"line":502},[198,787,737],{"class":215},[198,789,790],{"class":200,"line":627},[198,791,258],{"emptyLinePlaceholder":257},[198,793,794],{"class":200,"line":640},[198,795,796],{"class":271},"# Custom sentinels — identity is the whole point\n",[198,798,799,802,805,808],{"class":200,"line":645},[198,800,801],{"class":215},"_MISSING",[198,803,804],{"class":208}," =",[198,806,807],{"class":215}," object",[198,809,810],{"class":204},"()\n",[198,812,813],{"class":200,"line":662},[198,814,258],{"emptyLinePlaceholder":257},[198,816,817,820,823,826,828,830],{"class":200,"line":674},[198,818,819],{"class":208},"def",[198,821,822],{"class":323}," get",[198,824,825],{"class":204},"(mapping, key, default",[198,827,209],{"class":208},[198,829,801],{"class":215},[198,831,832],{"class":204},"):\n",[198,834,836,839,841,844,846],{"class":200,"line":835},15,[198,837,838],{"class":204},"    value ",[198,840,209],{"class":208},[198,842,843],{"class":204}," mapping.get(key, ",[198,845,801],{"class":215},[198,847,848],{"class":204},")\n",[198,850,852,855,858,860,863,866],{"class":200,"line":851},16,[198,853,854],{"class":208},"    if",[198,856,857],{"class":204}," value ",[198,859,33],{"class":208},[198,861,862],{"class":215}," _MISSING",[198,864,865],{"class":204},":   ",[198,867,868],{"class":271},"# distinguishes \"key absent\" from \"value is None\"\n",[198,870,872,875],{"class":200,"line":871},17,[198,873,874],{"class":208},"        return",[198,876,877],{"class":204}," default\n",[198,879,881,884],{"class":200,"line":880},18,[198,882,883],{"class":208},"    return",[198,885,886],{"class":204}," value\n",[15,888,889,891,892,894],{},[19,890,33],{}," is also correct as a fast-path optimisation inside ",[19,893,93],{}," itself:",[189,896,898],{"className":191,"code":897,"language":193,"meta":194,"style":194},"class Point:\n    def __eq__(self, other):\n        if self is other:           # same object → trivially equal\n            return True\n        if not isinstance(other, Point):\n            return NotImplemented\n        return self.x == other.x and self.y == other.y\n",[19,899,900,909,918,935,943,955,962],{"__ignoreMap":194},[198,901,902,904,907],{"class":200,"line":201},[198,903,320],{"class":208},[198,905,906],{"class":323}," Point",[198,908,327],{"class":204},[198,910,911,913,915],{"class":200,"line":232},[198,912,332],{"class":208},[198,914,335],{"class":215},[198,916,917],{"class":204},"(self, other):\n",[198,919,920,923,926,929,932],{"class":200,"line":254},[198,921,922],{"class":208},"        if",[198,924,925],{"class":215}," self",[198,927,928],{"class":208}," is",[198,930,931],{"class":204}," other:           ",[198,933,934],{"class":271},"# same object → trivially equal\n",[198,936,937,940],{"class":200,"line":261},[198,938,939],{"class":208},"            return",[198,941,942],{"class":215}," True\n",[198,944,945,947,949,952],{"class":200,"line":275},[198,946,922],{"class":208},[198,948,778],{"class":208},[198,950,951],{"class":215}," isinstance",[198,953,954],{"class":204},"(other, Point):\n",[198,956,957,959],{"class":200,"line":287},[198,958,939],{"class":208},[198,960,961],{"class":215}," NotImplemented\n",[198,963,964,966,968,971,973,976,979,981,984,986],{"class":200,"line":476},[198,965,874],{"class":208},[198,967,925],{"class":215},[198,969,970],{"class":204},".x ",[198,972,29],{"class":208},[198,974,975],{"class":204}," other.x ",[198,977,978],{"class":208},"and",[198,980,925],{"class":215},[198,982,983],{"class":204},".y ",[198,985,29],{"class":208},[198,987,988],{"class":204}," other.y\n",[10,990,992],{"id":991},"the-one-rule-decision-guide","The one-rule decision guide",[994,995,996],"blockquote",{},[15,997,998],{},[73,999,1000,1001,1003,1004,1006,1007,167,1009,167,1011,1013],{},"Use ",[19,1002,29],{}," to compare values. Use ",[19,1005,33],{}," only for ",[19,1008,166],{},[19,1010,113],{},[19,1012,118],{},", and your own\nsentinel objects.",[15,1015,1016,1017,1019,1020,1022,1023,1025,1026,1028,1029,1031],{},"If you're ever tempted to write ",[19,1018,33],{}," with a number, string, list, or any other value type,\nreplace it with ",[19,1021,29],{},". If swapping ",[19,1024,33],{}," for ",[19,1027,29],{}," would change the behaviour on any input,\nyou should have used ",[19,1030,29],{},".",[189,1033,1035],{"className":191,"code":1034,"language":193,"meta":194,"style":194},"# Wrong — relies on interning coincidence\nif name is \"admin\":     # SyntaxWarning in Python 3.8+\n    ...\n\n# Right\nif name == \"admin\":\n    ...\n\n# Wrong\nif count is 0:\n    ...\n\n# Right\nif count == 0:\n    ...\n\n# Right — singletons only\nif response is None:\n    ...\n",[19,1036,1037,1042,1060,1064,1068,1073,1085,1089,1093,1098,1112,1116,1120,1124,1136,1140,1144,1149,1162],{"__ignoreMap":194},[198,1038,1039],{"class":200,"line":201},[198,1040,1041],{"class":271},"# Wrong — relies on interning coincidence\n",[198,1043,1044,1046,1049,1051,1054,1057],{"class":200,"line":232},[198,1045,723],{"class":208},[198,1047,1048],{"class":204}," name ",[198,1050,33],{"class":208},[198,1052,1053],{"class":615}," \"admin\"",[198,1055,1056],{"class":204},":     ",[198,1058,1059],{"class":271},"# SyntaxWarning in Python 3.8+\n",[198,1061,1062],{"class":200,"line":254},[198,1063,737],{"class":215},[198,1065,1066],{"class":200,"line":261},[198,1067,258],{"emptyLinePlaceholder":257},[198,1069,1070],{"class":200,"line":275},[198,1071,1072],{"class":271},"# Right\n",[198,1074,1075,1077,1079,1081,1083],{"class":200,"line":287},[198,1076,723],{"class":208},[198,1078,1048],{"class":204},[198,1080,29],{"class":208},[198,1082,1053],{"class":615},[198,1084,327],{"class":204},[198,1086,1087],{"class":200,"line":476},[198,1088,737],{"class":215},[198,1090,1091],{"class":200,"line":490},[198,1092,258],{"emptyLinePlaceholder":257},[198,1094,1095],{"class":200,"line":502},[198,1096,1097],{"class":271},"# Wrong\n",[198,1099,1100,1102,1105,1107,1110],{"class":200,"line":627},[198,1101,723],{"class":208},[198,1103,1104],{"class":204}," count ",[198,1106,33],{"class":208},[198,1108,1109],{"class":215}," 0",[198,1111,327],{"class":204},[198,1113,1114],{"class":200,"line":640},[198,1115,737],{"class":215},[198,1117,1118],{"class":200,"line":645},[198,1119,258],{"emptyLinePlaceholder":257},[198,1121,1122],{"class":200,"line":662},[198,1123,1072],{"class":271},[198,1125,1126,1128,1130,1132,1134],{"class":200,"line":674},[198,1127,723],{"class":208},[198,1129,1104],{"class":204},[198,1131,29],{"class":208},[198,1133,1109],{"class":215},[198,1135,327],{"class":204},[198,1137,1138],{"class":200,"line":835},[198,1139,737],{"class":215},[198,1141,1142],{"class":200,"line":851},[198,1143,258],{"emptyLinePlaceholder":257},[198,1145,1146],{"class":200,"line":871},[198,1147,1148],{"class":271},"# Right — singletons only\n",[198,1150,1151,1153,1156,1158,1160],{"class":200,"line":880},[198,1152,723],{"class":208},[198,1154,1155],{"class":204}," response ",[198,1157,33],{"class":208},[198,1159,370],{"class":215},[198,1161,327],{"class":204},[198,1163,1165],{"class":200,"line":1164},19,[198,1166,737],{"class":215},[10,1168,1170],{"id":1169},"recap","Recap",[15,1172,1173,1177,1178,1180,1181,1185,1186,1188,1189,1191,1192,1194,1195,1198,1199,1202,1203,1031],{},[73,1174,1175],{},[19,1176,29],{}," tests value equality by calling ",[19,1179,93],{}," — use it for any comparison of data or\ncontent. ",[73,1182,1183],{},[19,1184,33],{}," tests object identity by comparing ",[19,1187,100],{}," — use it exclusively for\n",[19,1190,166],{},", the bool singletons, and custom sentinels. CPython's integer cache (−5..256) and\nstring interning make ",[19,1193,33],{}," appear to work on plain values inside the cache range, but this\nis a coincidence that breaks at the boundary and in non-CPython implementations. PEP 8\nmandates ",[19,1196,1197],{},"is None"," \u002F ",[19,1200,1201],{},"is not None","; everything else should be ",[19,1204,29],{},[994,1206,1207],{},[15,1208,1209,1210],{},"Deep dive: ",[1211,1212,1214],"a",{"href":1213},"\u002Fpython\u002Finternals\u002Fidentity-interning","Identity, is vs == & Interning — interview questions",[1216,1217,1218],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":194,"searchDepth":232,"depth":232,"links":1220},[1221,1222,1223,1225,1227,1229,1231,1232],{"id":12,"depth":232,"text":13},{"id":40,"depth":232,"text":41},{"id":175,"depth":232,"text":1224},"What == does",{"id":387,"depth":232,"text":1226},"What is does",{"id":513,"depth":232,"text":1228},"The interning trap — when is appears to work on values",{"id":696,"depth":232,"text":1230},"The correct uses of is",{"id":991,"depth":232,"text":992},{"id":1169,"depth":232,"text":1170},"Python == vs is explained — what each operator actually tests, when is \"accidentally\" works on numbers and strings, the only correct uses of is, and the one rule that makes the right choice automatic.","medium","md","Python",{},"\u002Fblog\u002Fpython-is-vs-equals-equality-vs-identity",{"title":5,"description":1233},"blog\u002Fpython-is-vs-equals-equality-vs-identity","== vs is — Equality vs Identity","Memory & Internals","internals","2026-06-21","R6HgDcvSSKXNMEZbafLAwXPGiqHTn7j9nGPuv7KMofs",1782244087921]