[{"data":1,"prerenderedAt":782},["ShallowReactive",2],{"blog-\u002Fblog\u002Fpython-sets-frozensets-explained":3},{"id":4,"title":5,"body":6,"description":768,"difficulty":769,"extension":770,"framework":771,"frameworkSlug":32,"meta":772,"navigation":195,"order":199,"path":773,"qaPath":774,"seo":775,"stem":776,"subtopic":777,"topic":778,"topicSlug":779,"updated":780,"__hash__":781},"blog\u002Fblog\u002Fpython-sets-frozensets-explained.md","Python Sets and Frozensets Explained — Set Operations, O(1) Membership, and Dedup",{"type":7,"value":8,"toc":757},"minimark",[9,14,23,27,124,135,139,142,282,293,297,311,358,362,365,407,418,459,463,466,539,550,554,557,606,610,625,699,717,721,753],[10,11,13],"h2",{"id":12},"python-sets-explained","Python sets, explained",[15,16,17,18,22],"p",{},"A set is an unordered collection of ",[19,20,21],"strong",{},"unique, hashable"," elements, backed by a hash table.\nThat backing is what makes sets brilliant for membership tests and de-duplication — and\nwhy a frozenset exists. This guide walks through operations, performance, and the mutating\nmethods.",[10,24,26],{"id":25},"creating-sets","Creating sets",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-python shiki shiki-themes github-light github-dark","s = {1, 2, 3}            # set literal\ns = set([1, 2, 2, 3])    # {1, 2, 3} — duplicates dropped\nempty = set()            # {} is an empty DICT, not a set!\n","python","",[35,36,37,75,108],"code",{"__ignoreMap":33},[38,39,42,46,50,53,57,60,63,65,68,71],"span",{"class":40,"line":41},"line",1,[38,43,45],{"class":44},"sVt8B","s ",[38,47,49],{"class":48},"szBVR","=",[38,51,52],{"class":44}," {",[38,54,56],{"class":55},"sj4cs","1",[38,58,59],{"class":44},", ",[38,61,62],{"class":55},"2",[38,64,59],{"class":44},[38,66,67],{"class":55},"3",[38,69,70],{"class":44},"}            ",[38,72,74],{"class":73},"sJ8bj","# set literal\n",[38,76,78,80,82,85,88,90,92,94,96,98,100,102,105],{"class":40,"line":77},2,[38,79,45],{"class":44},[38,81,49],{"class":48},[38,83,84],{"class":55}," set",[38,86,87],{"class":44},"([",[38,89,56],{"class":55},[38,91,59],{"class":44},[38,93,62],{"class":55},[38,95,59],{"class":44},[38,97,62],{"class":55},[38,99,59],{"class":44},[38,101,67],{"class":55},[38,103,104],{"class":44},"])    ",[38,106,107],{"class":73},"# {1, 2, 3} — duplicates dropped\n",[38,109,111,114,116,118,121],{"class":40,"line":110},3,[38,112,113],{"class":44},"empty ",[38,115,49],{"class":48},[38,117,84],{"class":55},[38,119,120],{"class":44},"()            ",[38,122,123],{"class":73},"# {} is an empty DICT, not a set!\n",[15,125,126,127,130,131,134],{},"That last line is a classic trap: ",[35,128,129],{},"{}"," is an empty dictionary; you must use ",[35,132,133],{},"set()"," for an\nempty set.",[10,136,138],{"id":137},"set-operations","Set operations",[15,140,141],{},"Sets support mathematical operations as both operators and methods:",[28,143,145],{"className":30,"code":144,"language":32,"meta":33,"style":33},"a = {1, 2, 3}\nb = {2, 3, 4}\n\na | b      # {1, 2, 3, 4}  — union           (a.union(b))\na & b      # {2, 3}        — intersection     (a.intersection(b))\na - b      # {1}           — difference       (a.difference(b))\na ^ b      # {1, 4}        — symmetric diff   (a.symmetric_difference(b))\n\na \u003C= b     # subset check\na >= b     # superset check\n",[35,146,147,169,191,197,211,224,237,250,255,269],{"__ignoreMap":33},[38,148,149,152,154,156,158,160,162,164,166],{"class":40,"line":41},[38,150,151],{"class":44},"a ",[38,153,49],{"class":48},[38,155,52],{"class":44},[38,157,56],{"class":55},[38,159,59],{"class":44},[38,161,62],{"class":55},[38,163,59],{"class":44},[38,165,67],{"class":55},[38,167,168],{"class":44},"}\n",[38,170,171,174,176,178,180,182,184,186,189],{"class":40,"line":77},[38,172,173],{"class":44},"b ",[38,175,49],{"class":48},[38,177,52],{"class":44},[38,179,62],{"class":55},[38,181,59],{"class":44},[38,183,67],{"class":55},[38,185,59],{"class":44},[38,187,188],{"class":55},"4",[38,190,168],{"class":44},[38,192,193],{"class":40,"line":110},[38,194,196],{"emptyLinePlaceholder":195},true,"\n",[38,198,200,202,205,208],{"class":40,"line":199},4,[38,201,151],{"class":44},[38,203,204],{"class":48},"|",[38,206,207],{"class":44}," b      ",[38,209,210],{"class":73},"# {1, 2, 3, 4}  — union           (a.union(b))\n",[38,212,214,216,219,221],{"class":40,"line":213},5,[38,215,151],{"class":44},[38,217,218],{"class":48},"&",[38,220,207],{"class":44},[38,222,223],{"class":73},"# {2, 3}        — intersection     (a.intersection(b))\n",[38,225,227,229,232,234],{"class":40,"line":226},6,[38,228,151],{"class":44},[38,230,231],{"class":48},"-",[38,233,207],{"class":44},[38,235,236],{"class":73},"# {1}           — difference       (a.difference(b))\n",[38,238,240,242,245,247],{"class":40,"line":239},7,[38,241,151],{"class":44},[38,243,244],{"class":48},"^",[38,246,207],{"class":44},[38,248,249],{"class":73},"# {1, 4}        — symmetric diff   (a.symmetric_difference(b))\n",[38,251,253],{"class":40,"line":252},8,[38,254,196],{"emptyLinePlaceholder":195},[38,256,258,260,263,266],{"class":40,"line":257},9,[38,259,151],{"class":44},[38,261,262],{"class":48},"\u003C=",[38,264,265],{"class":44}," b     ",[38,267,268],{"class":73},"# subset check\n",[38,270,272,274,277,279],{"class":40,"line":271},10,[38,273,151],{"class":44},[38,275,276],{"class":48},">=",[38,278,265],{"class":44},[38,280,281],{"class":73},"# superset check\n",[15,283,284,285,288,289,292],{},"The method forms (",[35,286,287],{},"a.union(b)",") accept any iterable, not just another set, which is handy:\n",[35,290,291],{},"a.union([4, 5])",".",[10,294,296],{"id":295},"why-membership-testing-is-o1","Why membership testing is O(1)",[15,298,299,302,303,306,307,310],{},[35,300,301],{},"x in some_set"," is O(1) average, because a set hashes ",[35,304,305],{},"x"," and jumps straight to its bucket.\n",[35,308,309],{},"x in some_list"," is O(n) because it scans element by element. For repeated lookups against a\nlarge collection, converting to a set is a big win:",[28,312,314],{"className":30,"code":313,"language":32,"meta":33,"style":33},"allowed = {\"GET\", \"POST\", \"PUT\"}     # set — O(1) lookups\n\"GET\" in allowed                     # fast regardless of size\n",[35,315,316,345],{"__ignoreMap":33},[38,317,318,321,323,325,329,331,334,336,339,342],{"class":40,"line":41},[38,319,320],{"class":44},"allowed ",[38,322,49],{"class":48},[38,324,52],{"class":44},[38,326,328],{"class":327},"sZZnC","\"GET\"",[38,330,59],{"class":44},[38,332,333],{"class":327},"\"POST\"",[38,335,59],{"class":44},[38,337,338],{"class":327},"\"PUT\"",[38,340,341],{"class":44},"}     ",[38,343,344],{"class":73},"# set — O(1) lookups\n",[38,346,347,349,352,355],{"class":40,"line":77},[38,348,328],{"class":327},[38,350,351],{"class":48}," in",[38,353,354],{"class":44}," allowed                     ",[38,356,357],{"class":73},"# fast regardless of size\n",[10,359,361],{"id":360},"removing-duplicates","Removing duplicates",[15,363,364],{},"The most common everyday use of a set is de-duplication:",[28,366,368],{"className":30,"code":367,"language":32,"meta":33,"style":33},"list(set([3, 1, 2, 3, 1]))     # [1, 2, 3] — order NOT guaranteed\n",[35,369,370],{"__ignoreMap":33},[38,371,372,375,378,381,383,385,387,389,391,393,395,397,399,401,404],{"class":40,"line":41},[38,373,374],{"class":55},"list",[38,376,377],{"class":44},"(",[38,379,380],{"class":55},"set",[38,382,87],{"class":44},[38,384,67],{"class":55},[38,386,59],{"class":44},[38,388,56],{"class":55},[38,390,59],{"class":44},[38,392,62],{"class":55},[38,394,59],{"class":44},[38,396,67],{"class":55},[38,398,59],{"class":44},[38,400,56],{"class":55},[38,402,403],{"class":44},"]))     ",[38,405,406],{"class":73},"# [1, 2, 3] — order NOT guaranteed\n",[15,408,409,410,413,414,417],{},"If you need to drop duplicates ",[19,411,412],{},"while preserving order",", use ",[35,415,416],{},"dict.fromkeys",", which keeps\ninsertion order:",[28,419,421],{"className":30,"code":420,"language":32,"meta":33,"style":33},"list(dict.fromkeys([3, 1, 2, 3, 1]))   # [3, 1, 2]\n",[35,422,423],{"__ignoreMap":33},[38,424,425,427,429,432,435,437,439,441,443,445,447,449,451,453,456],{"class":40,"line":41},[38,426,374],{"class":55},[38,428,377],{"class":44},[38,430,431],{"class":55},"dict",[38,433,434],{"class":44},".fromkeys([",[38,436,67],{"class":55},[38,438,59],{"class":44},[38,440,56],{"class":55},[38,442,59],{"class":44},[38,444,62],{"class":55},[38,446,59],{"class":44},[38,448,67],{"class":55},[38,450,59],{"class":44},[38,452,56],{"class":55},[38,454,455],{"class":44},"]))   ",[38,457,458],{"class":73},"# [3, 1, 2]\n",[10,460,462],{"id":461},"add-discard-and-remove","add, discard, and remove",[15,464,465],{},"Three methods change a set; the difference is how they handle a missing element:",[28,467,469],{"className":30,"code":468,"language":32,"meta":33,"style":33},"s = {1, 2, 3}\ns.add(4)         # {1, 2, 3, 4}\ns.remove(2)      # {1, 3, 4}; KeyError if 2 weren't present\ns.discard(99)    # no error even though 99 isn't there\ns.pop()          # removes and returns an arbitrary element\n",[35,470,471,491,504,517,531],{"__ignoreMap":33},[38,472,473,475,477,479,481,483,485,487,489],{"class":40,"line":41},[38,474,45],{"class":44},[38,476,49],{"class":48},[38,478,52],{"class":44},[38,480,56],{"class":55},[38,482,59],{"class":44},[38,484,62],{"class":55},[38,486,59],{"class":44},[38,488,67],{"class":55},[38,490,168],{"class":44},[38,492,493,496,498,501],{"class":40,"line":77},[38,494,495],{"class":44},"s.add(",[38,497,188],{"class":55},[38,499,500],{"class":44},")         ",[38,502,503],{"class":73},"# {1, 2, 3, 4}\n",[38,505,506,509,511,514],{"class":40,"line":110},[38,507,508],{"class":44},"s.remove(",[38,510,62],{"class":55},[38,512,513],{"class":44},")      ",[38,515,516],{"class":73},"# {1, 3, 4}; KeyError if 2 weren't present\n",[38,518,519,522,525,528],{"class":40,"line":199},[38,520,521],{"class":44},"s.discard(",[38,523,524],{"class":55},"99",[38,526,527],{"class":44},")    ",[38,529,530],{"class":73},"# no error even though 99 isn't there\n",[38,532,533,536],{"class":40,"line":213},[38,534,535],{"class":44},"s.pop()          ",[38,537,538],{"class":73},"# removes and returns an arbitrary element\n",[15,540,541,542,545,546,549],{},"Use ",[35,543,544],{},"discard"," when \"remove if present\" is the intent; use ",[35,547,548],{},"remove"," when absence is a bug\nworth surfacing.",[10,551,553],{"id":552},"elements-must-be-hashable","Elements must be hashable",[15,555,556],{},"Because sets use hashing, every element must be hashable (immutable). You can put numbers,\nstrings, and tuples in a set, but not lists or other sets:",[28,558,560],{"className":30,"code":559,"language":32,"meta":33,"style":33},"{1, \"a\", (2, 3)}    # fine\n{[1, 2]}            # TypeError: unhashable type: 'list'\n",[35,561,562,589],{"__ignoreMap":33},[38,563,564,567,569,571,574,577,579,581,583,586],{"class":40,"line":41},[38,565,566],{"class":44},"{",[38,568,56],{"class":55},[38,570,59],{"class":44},[38,572,573],{"class":327},"\"a\"",[38,575,576],{"class":44},", (",[38,578,62],{"class":55},[38,580,59],{"class":44},[38,582,67],{"class":55},[38,584,585],{"class":44},")}    ",[38,587,588],{"class":73},"# fine\n",[38,590,591,594,596,598,600,603],{"class":40,"line":77},[38,592,593],{"class":44},"{[",[38,595,56],{"class":55},[38,597,59],{"class":44},[38,599,62],{"class":55},[38,601,602],{"class":44},"]}            ",[38,604,605],{"class":73},"# TypeError: unhashable type: 'list'\n",[10,607,609],{"id":608},"frozenset-the-immutable-set","frozenset — the immutable set",[15,611,612,613,616,617,620,621,624],{},"A ",[35,614,615],{},"frozenset"," is an immutable, hashable set. Because it's hashable, it can be a ",[19,618,619],{},"dict key","\nor an ",[19,622,623],{},"element of another set"," — things a normal set cannot do:",[28,626,628],{"className":30,"code":627,"language":32,"meta":33,"style":33},"fs = frozenset({1, 2, 3})\n{fs: \"value\"}                  # frozenset as a dict key — works\n{frozenset({1, 2}), frozenset({3})}   # a set of sets — works\n",[35,629,630,656,670],{"__ignoreMap":33},[38,631,632,635,637,640,643,645,647,649,651,653],{"class":40,"line":41},[38,633,634],{"class":44},"fs ",[38,636,49],{"class":48},[38,638,639],{"class":55}," frozenset",[38,641,642],{"class":44},"({",[38,644,56],{"class":55},[38,646,59],{"class":44},[38,648,62],{"class":55},[38,650,59],{"class":44},[38,652,67],{"class":55},[38,654,655],{"class":44},"})\n",[38,657,658,661,664,667],{"class":40,"line":77},[38,659,660],{"class":44},"{fs: ",[38,662,663],{"class":327},"\"value\"",[38,665,666],{"class":44},"}                  ",[38,668,669],{"class":73},"# frozenset as a dict key — works\n",[38,671,672,674,676,678,680,682,684,687,689,691,693,696],{"class":40,"line":110},[38,673,566],{"class":44},[38,675,615],{"class":55},[38,677,642],{"class":44},[38,679,56],{"class":55},[38,681,59],{"class":44},[38,683,62],{"class":55},[38,685,686],{"class":44},"}), ",[38,688,615],{"class":55},[38,690,642],{"class":44},[38,692,67],{"class":55},[38,694,695],{"class":44},"})}   ",[38,697,698],{"class":73},"# a set of sets — works\n",[15,700,701,702,59,704,59,706,709,710,713,714,716],{},"It supports all the read-only operations (",[35,703,204],{},[35,705,218],{},[35,707,708],{},"in",") but none that mutate (",[35,711,712],{},"add",",\n",[35,715,548],{},").",[10,718,720],{"id":719},"recap","Recap",[15,722,723,724,727,728,59,730,59,732,59,734,736,737,740,741,744,745,747,748,750,751,292],{},"A set is an unordered collection of unique, hashable elements with ",[19,725,726],{},"O(1)"," membership\ntests — far faster than a list for \"is this in here?\". Use ",[35,729,204],{},[35,731,218],{},[35,733,231],{},[35,735,244],{}," for union,\nintersection, difference, and symmetric difference. ",[35,738,739],{},"set(seq)"," de-duplicates (order lost);\n",[35,742,743],{},"dict.fromkeys(seq)"," de-duplicates while keeping order. Use ",[35,746,544],{}," for safe removal and\n",[35,749,548],{}," when absence should raise. Elements must be hashable, and when you need an\nimmutable set you can use as a dict key or nest inside another set, reach for ",[35,752,615],{},[754,755,756],"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 .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":33,"searchDepth":77,"depth":77,"links":758},[759,760,761,762,763,764,765,766,767],{"id":12,"depth":77,"text":13},{"id":25,"depth":77,"text":26},{"id":137,"depth":77,"text":138},{"id":295,"depth":77,"text":296},{"id":360,"depth":77,"text":361},{"id":461,"depth":77,"text":462},{"id":552,"depth":77,"text":553},{"id":608,"depth":77,"text":609},{"id":719,"depth":77,"text":720},"How Python sets work — union\u002Fintersection\u002Fdifference, why membership testing is O(1), removing duplicates, add vs discard vs remove, and when you need a frozenset.","medium","md","Python",{},"\u002Fblog\u002Fpython-sets-frozensets-explained","\u002Fpython\u002Fdata-structures\u002Fsets",{"title":5,"description":768},"blog\u002Fpython-sets-frozensets-explained","Sets & Frozensets","Data Structures","data-structures","2026-06-19","zCAX7j-162-ilZmmWgx5A8FpePLPCZ6JoejgLw-Dm00",1782244093897]