[{"data":1,"prerenderedAt":1285},["ShallowReactive",2],{"blog-\u002Fblog\u002Fpython-classmethod-vs-staticmethod-vs-instance-method":3},{"id":4,"title":5,"body":6,"description":1272,"difficulty":1273,"extension":1274,"framework":1275,"frameworkSlug":204,"meta":1276,"navigation":247,"order":263,"path":1277,"qaPath":662,"seo":1278,"stem":1279,"subtopic":1280,"topic":1281,"topicSlug":1282,"updated":1283,"__hash__":1284},"blog\u002Fblog\u002Fpython-classmethod-vs-staticmethod-vs-instance-method.md","Python @classmethod vs @staticmethod vs Instance Method — When to Use Each",{"type":7,"value":8,"toc":1260},"minimark",[9,14,23,27,183,187,199,359,362,368,380,564,588,638,653,664,670,677,839,846,850,859,976,987,991,994,1027,1223,1227,1256],[10,11,13],"h2",{"id":12},"three-method-types-one-class","Three method types, one class",[15,16,17,18,22],"p",{},"Python classes support three kinds of methods, and the distinction trips up almost every\ndeveloper at some point. The difference is not about access control — it's about ",[19,20,21],"strong",{},"what\nthe method receives as its implicit first argument",", which determines what it can see and\ndo.",[10,24,26],{"id":25},"quick-reference-comparison","Quick-reference comparison",[28,29,30,53],"table",{},[31,32,33],"thead",{},[34,35,36,39,42,48],"tr",{},[37,38],"th",{},[37,40,41],{},"Instance method",[37,43,44],{},[45,46,47],"code",{},"@classmethod",[37,49,50],{},[45,51,52],{},"@staticmethod",[54,55,56,79,94,118,132,146,167],"tbody",{},[34,57,58,64,70,76],{},[59,60,61],"td",{},[19,62,63],{},"First argument",[59,65,66,69],{},[45,67,68],{},"self"," — the instance",[59,71,72,75],{},[45,73,74],{},"cls"," — the class itself",[59,77,78],{},"Nothing — no implicit arg",[34,80,81,86,89,92],{},[59,82,83],{},[19,84,85],{},"Access to instance?",[59,87,88],{},"Yes",[59,90,91],{},"No",[59,93,91],{},[34,95,96,101,112,116],{},[59,97,98],{},[19,99,100],{},"Access to class?",[59,102,103,104,107,108,111],{},"Yes (via ",[45,105,106],{},"type(self)"," or ",[45,109,110],{},"self.__class__",")",[59,113,103,114,111],{},[45,115,74],{},[59,117,91],{},[34,119,120,125,128,130],{},[59,121,122],{},[19,123,124],{},"Callable on class?",[59,126,127],{},"No (needs an instance)",[59,129,88],{},[59,131,88],{},[34,133,134,139,141,144],{},[59,135,136],{},[19,137,138],{},"Callable on instance?",[59,140,88],{},[59,142,143],{},"Yes (cls is still the class)",[59,145,88],{},[34,147,148,153,159,164],{},[59,149,150],{},[19,151,152],{},"Subclass safe?",[59,154,155,156,158],{},"Yes — ",[45,157,106],{}," gives subclass",[59,160,155,161,163],{},[45,162,74],{}," gives the subclass",[59,165,166],{},"No — no class reference at all",[34,168,169,174,177,180],{},[59,170,171],{},[19,172,173],{},"Main use",[59,175,176],{},"Per-object behaviour",[59,178,179],{},"Alternative constructors, class-level logic",[59,181,182],{},"Utility helpers with no class\u002Finstance coupling",[10,184,186],{"id":185},"instance-methods-the-default","Instance methods — the default",[15,188,189,190,192,193,195,196,198],{},"An instance method takes ",[45,191,68],{}," as its first argument and operates on one particular\nobject. It has full access to instance state and can also reach the class via ",[45,194,106],{},"\nor ",[45,197,110],{},".",[200,201,206],"pre",{"className":202,"code":203,"language":204,"meta":205,"style":205},"language-python shiki shiki-themes github-light github-dark","class BankAccount:\n    interest_rate = 0.05          # class-level state\n\n    def __init__(self, balance):\n        self.balance = balance    # instance-level state\n\n    def deposit(self, amount):    # instance method — needs self\n        self.balance += amount\n        return self.balance\n\naccount = BankAccount(1000)\naccount.deposit(200)              # self = account, amount = 200\n","python","",[45,207,208,225,242,249,261,278,283,297,310,322,327,344],{"__ignoreMap":205},[209,210,213,217,221],"span",{"class":211,"line":212},"line",1,[209,214,216],{"class":215},"szBVR","class",[209,218,220],{"class":219},"sScJk"," BankAccount",[209,222,224],{"class":223},"sVt8B",":\n",[209,226,228,231,234,238],{"class":211,"line":227},2,[209,229,230],{"class":223},"    interest_rate ",[209,232,233],{"class":215},"=",[209,235,237],{"class":236},"sj4cs"," 0.05",[209,239,241],{"class":240},"sJ8bj","          # class-level state\n",[209,243,245],{"class":211,"line":244},3,[209,246,248],{"emptyLinePlaceholder":247},true,"\n",[209,250,252,255,258],{"class":211,"line":251},4,[209,253,254],{"class":215},"    def",[209,256,257],{"class":236}," __init__",[209,259,260],{"class":223},"(self, balance):\n",[209,262,264,267,270,272,275],{"class":211,"line":263},5,[209,265,266],{"class":236},"        self",[209,268,269],{"class":223},".balance ",[209,271,233],{"class":215},[209,273,274],{"class":223}," balance    ",[209,276,277],{"class":240},"# instance-level state\n",[209,279,281],{"class":211,"line":280},6,[209,282,248],{"emptyLinePlaceholder":247},[209,284,286,288,291,294],{"class":211,"line":285},7,[209,287,254],{"class":215},[209,289,290],{"class":219}," deposit",[209,292,293],{"class":223},"(self, amount):    ",[209,295,296],{"class":240},"# instance method — needs self\n",[209,298,300,302,304,307],{"class":211,"line":299},8,[209,301,266],{"class":236},[209,303,269],{"class":223},[209,305,306],{"class":215},"+=",[209,308,309],{"class":223}," amount\n",[209,311,313,316,319],{"class":211,"line":312},9,[209,314,315],{"class":215},"        return",[209,317,318],{"class":236}," self",[209,320,321],{"class":223},".balance\n",[209,323,325],{"class":211,"line":324},10,[209,326,248],{"emptyLinePlaceholder":247},[209,328,330,333,335,338,341],{"class":211,"line":329},11,[209,331,332],{"class":223},"account ",[209,334,233],{"class":215},[209,336,337],{"class":223}," BankAccount(",[209,339,340],{"class":236},"1000",[209,342,343],{"class":223},")\n",[209,345,347,350,353,356],{"class":211,"line":346},12,[209,348,349],{"class":223},"account.deposit(",[209,351,352],{"class":236},"200",[209,354,355],{"class":223},")              ",[209,357,358],{"class":240},"# self = account, amount = 200\n",[15,360,361],{},"Instance methods are the right choice for anything that operates on or mutates a specific\nobject's state.",[10,363,365,367],{"id":364},"classmethod-the-alternative-constructor-pattern",[45,366,47],{}," — the alternative constructor pattern",[15,369,370,371,375,376,379],{},"A classmethod receives ",[19,372,373],{},[45,374,74],{}," (the class, not an instance) as its first argument. It\ncan't see instance state, but it can create instances, read or modify class-level\nattributes, and call other class methods. The most common use is an ",[19,377,378],{},"alternative\nconstructor"," — a named factory method for building instances from a different input\nformat.",[200,381,383],{"className":202,"code":382,"language":204,"meta":205,"style":205},"class Date:\n    def __init__(self, year, month, day):\n        self.year, self.month, self.day = year, month, day\n\n    @classmethod\n    def from_string(cls, text):         # alternative constructor\n        year, month, day = map(int, text.split(\"-\"))\n        return cls(year, month, day)    # cls, not Date — subclass safe\n\n    @classmethod\n    def today(cls):\n        import datetime\n        t = datetime.date.today()\n        return cls(t.year, t.month, t.day)\n\nDate.from_string(\"2026-06-21\")          # no instance needed\nDate.today()\n",[45,384,385,394,403,425,429,437,450,476,489,493,499,509,517,528,538,543,558],{"__ignoreMap":205},[209,386,387,389,392],{"class":211,"line":212},[209,388,216],{"class":215},[209,390,391],{"class":219}," Date",[209,393,224],{"class":223},[209,395,396,398,400],{"class":211,"line":227},[209,397,254],{"class":215},[209,399,257],{"class":236},[209,401,402],{"class":223},"(self, year, month, day):\n",[209,404,405,407,410,412,415,417,420,422],{"class":211,"line":244},[209,406,266],{"class":236},[209,408,409],{"class":223},".year, ",[209,411,68],{"class":236},[209,413,414],{"class":223},".month, ",[209,416,68],{"class":236},[209,418,419],{"class":223},".day ",[209,421,233],{"class":215},[209,423,424],{"class":223}," year, month, day\n",[209,426,427],{"class":211,"line":251},[209,428,248],{"emptyLinePlaceholder":247},[209,430,431,434],{"class":211,"line":263},[209,432,433],{"class":219},"    @",[209,435,436],{"class":236},"classmethod\n",[209,438,439,441,444,447],{"class":211,"line":280},[209,440,254],{"class":215},[209,442,443],{"class":219}," from_string",[209,445,446],{"class":223},"(cls, text):         ",[209,448,449],{"class":240},"# alternative constructor\n",[209,451,452,455,457,460,463,466,469,473],{"class":211,"line":285},[209,453,454],{"class":223},"        year, month, day ",[209,456,233],{"class":215},[209,458,459],{"class":236}," map",[209,461,462],{"class":223},"(",[209,464,465],{"class":236},"int",[209,467,468],{"class":223},", text.split(",[209,470,472],{"class":471},"sZZnC","\"-\"",[209,474,475],{"class":223},"))\n",[209,477,478,480,483,486],{"class":211,"line":299},[209,479,315],{"class":215},[209,481,482],{"class":236}," cls",[209,484,485],{"class":223},"(year, month, day)    ",[209,487,488],{"class":240},"# cls, not Date — subclass safe\n",[209,490,491],{"class":211,"line":312},[209,492,248],{"emptyLinePlaceholder":247},[209,494,495,497],{"class":211,"line":324},[209,496,433],{"class":219},[209,498,436],{"class":236},[209,500,501,503,506],{"class":211,"line":329},[209,502,254],{"class":215},[209,504,505],{"class":219}," today",[209,507,508],{"class":223},"(cls):\n",[209,510,511,514],{"class":211,"line":346},[209,512,513],{"class":215},"        import",[209,515,516],{"class":223}," datetime\n",[209,518,520,523,525],{"class":211,"line":519},13,[209,521,522],{"class":223},"        t ",[209,524,233],{"class":215},[209,526,527],{"class":223}," datetime.date.today()\n",[209,529,531,533,535],{"class":211,"line":530},14,[209,532,315],{"class":215},[209,534,482],{"class":236},[209,536,537],{"class":223},"(t.year, t.month, t.day)\n",[209,539,541],{"class":211,"line":540},15,[209,542,248],{"emptyLinePlaceholder":247},[209,544,546,549,552,555],{"class":211,"line":545},16,[209,547,548],{"class":223},"Date.from_string(",[209,550,551],{"class":471},"\"2026-06-21\"",[209,553,554],{"class":223},")          ",[209,556,557],{"class":240},"# no instance needed\n",[209,559,561],{"class":211,"line":560},17,[209,562,563],{"class":223},"Date.today()\n",[15,565,566,576,577,579,580,584,585,587],{},[19,567,568,569,571,572,575],{},"Why ",[45,570,74],{}," instead of ",[45,573,574],{},"Date","?"," Subclasses inherit the classmethod. Using ",[45,578,74],{}," means a\nsubclass gets an instance of ",[581,582,583],"em",{},"itself"," — using the hard-coded class name ",[45,586,574],{}," breaks\nsubclassing:",[200,589,591],{"className":202,"code":590,"language":204,"meta":205,"style":205},"class ExtendedDate(Date):\n    pass\n\ntype(ExtendedDate.from_string(\"2026-01-01\"))   # ExtendedDate — correct with cls\n# would be Date — wrong if from_string() used `Date(...)` directly\n",[45,592,593,607,612,616,633],{"__ignoreMap":205},[209,594,595,597,600,602,604],{"class":211,"line":212},[209,596,216],{"class":215},[209,598,599],{"class":219}," ExtendedDate",[209,601,462],{"class":223},[209,603,574],{"class":219},[209,605,606],{"class":223},"):\n",[209,608,609],{"class":211,"line":227},[209,610,611],{"class":215},"    pass\n",[209,613,614],{"class":211,"line":244},[209,615,248],{"emptyLinePlaceholder":247},[209,617,618,621,624,627,630],{"class":211,"line":251},[209,619,620],{"class":236},"type",[209,622,623],{"class":223},"(ExtendedDate.from_string(",[209,625,626],{"class":471},"\"2026-01-01\"",[209,628,629],{"class":223},"))   ",[209,631,632],{"class":240},"# ExtendedDate — correct with cls\n",[209,634,635],{"class":211,"line":263},[209,636,637],{"class":240},"# would be Date — wrong if from_string() used `Date(...)` directly\n",[15,639,640,641,644,645,648,649,652],{},"This is the same pattern as ",[45,642,643],{},"dict.fromkeys",", ",[45,646,647],{},"datetime.datetime.fromtimestamp",", and\n",[45,650,651],{},"int.from_bytes"," in the standard library.",[654,655,656],"blockquote",{},[15,657,658,659],{},"Deep dive: ",[660,661,663],"a",{"href":662},"\u002Fpython\u002Foop\u002Fmethods-properties","Methods & Properties interview questions",[10,665,667,669],{"id":666},"staticmethod-a-regular-function-inside-the-class-namespace",[45,668,52],{}," — a regular function inside the class namespace",[15,671,672,673,676],{},"A staticmethod receives ",[19,674,675],{},"no implicit first argument"," — it's a plain function that lives\ninside the class for organisational reasons only. It has no access to instance or class\nstate unless you pass something in explicitly.",[200,678,680],{"className":202,"code":679,"language":204,"meta":205,"style":205},"class Temperature:\n    def __init__(self, celsius):\n        self.celsius = celsius\n\n    def to_fahrenheit(self):                # instance method\n        return self.celsius * 9\u002F5 + 32\n\n    @staticmethod\n    def celsius_to_fahrenheit(c):           # no self, no cls\n        return c * 9\u002F5 + 32                 # pure conversion helper\n\nTemperature.celsius_to_fahrenheit(100)      # 212.0 — no instance needed\nTemperature(0).celsius_to_fahrenheit(100)   # same result — self is not passed\n",[45,681,682,691,700,712,716,729,755,759,766,779,802,806,820],{"__ignoreMap":205},[209,683,684,686,689],{"class":211,"line":212},[209,685,216],{"class":215},[209,687,688],{"class":219}," Temperature",[209,690,224],{"class":223},[209,692,693,695,697],{"class":211,"line":227},[209,694,254],{"class":215},[209,696,257],{"class":236},[209,698,699],{"class":223},"(self, celsius):\n",[209,701,702,704,707,709],{"class":211,"line":244},[209,703,266],{"class":236},[209,705,706],{"class":223},".celsius ",[209,708,233],{"class":215},[209,710,711],{"class":223}," celsius\n",[209,713,714],{"class":211,"line":251},[209,715,248],{"emptyLinePlaceholder":247},[209,717,718,720,723,726],{"class":211,"line":263},[209,719,254],{"class":215},[209,721,722],{"class":219}," to_fahrenheit",[209,724,725],{"class":223},"(self):                ",[209,727,728],{"class":240},"# instance method\n",[209,730,731,733,735,737,740,743,746,749,752],{"class":211,"line":280},[209,732,315],{"class":215},[209,734,318],{"class":236},[209,736,706],{"class":223},[209,738,739],{"class":215},"*",[209,741,742],{"class":236}," 9",[209,744,745],{"class":215},"\u002F",[209,747,748],{"class":236},"5",[209,750,751],{"class":215}," +",[209,753,754],{"class":236}," 32\n",[209,756,757],{"class":211,"line":285},[209,758,248],{"emptyLinePlaceholder":247},[209,760,761,763],{"class":211,"line":299},[209,762,433],{"class":219},[209,764,765],{"class":236},"staticmethod\n",[209,767,768,770,773,776],{"class":211,"line":312},[209,769,254],{"class":215},[209,771,772],{"class":219}," celsius_to_fahrenheit",[209,774,775],{"class":223},"(c):           ",[209,777,778],{"class":240},"# no self, no cls\n",[209,780,781,783,786,788,790,792,794,796,799],{"class":211,"line":324},[209,782,315],{"class":215},[209,784,785],{"class":223}," c ",[209,787,739],{"class":215},[209,789,742],{"class":236},[209,791,745],{"class":215},[209,793,748],{"class":236},[209,795,751],{"class":215},[209,797,798],{"class":236}," 32",[209,800,801],{"class":240},"                 # pure conversion helper\n",[209,803,804],{"class":211,"line":329},[209,805,248],{"emptyLinePlaceholder":247},[209,807,808,811,814,817],{"class":211,"line":346},[209,809,810],{"class":223},"Temperature.celsius_to_fahrenheit(",[209,812,813],{"class":236},"100",[209,815,816],{"class":223},")      ",[209,818,819],{"class":240},"# 212.0 — no instance needed\n",[209,821,822,825,828,831,833,836],{"class":211,"line":519},[209,823,824],{"class":223},"Temperature(",[209,826,827],{"class":236},"0",[209,829,830],{"class":223},").celsius_to_fahrenheit(",[209,832,813],{"class":236},[209,834,835],{"class":223},")   ",[209,837,838],{"class":240},"# same result — self is not passed\n",[15,840,841,842,845],{},"Use a staticmethod when the logic is ",[19,843,844],{},"related to the class conceptually"," (so you want it\nin the same namespace) but doesn't actually need to touch the class or any instance.",[10,847,849],{"id":848},"the-subclass-safety-rule","The subclass safety rule",[15,851,852,853,855,856,858],{},"The biggest practical difference between ",[45,854,47],{}," and ",[45,857,52],{}," is subclass\nbehaviour. A classmethod knows which (sub)class it was called on; a staticmethod doesn't:",[200,860,862],{"className":202,"code":861,"language":204,"meta":205,"style":205},"class Shape:\n    @classmethod\n    def default(cls):\n        return cls()          # builds the right subtype\n\n    @staticmethod\n    def default_bad():\n        return Shape()        # always Shape, never the subclass\n\nclass Circle(Shape):\n    pass\n\ntype(Circle.default())        # Circle  — correct\ntype(Circle.default_bad())    # Shape   — wrong\n",[45,863,864,873,879,888,900,904,910,920,930,934,948,952,956,966],{"__ignoreMap":205},[209,865,866,868,871],{"class":211,"line":212},[209,867,216],{"class":215},[209,869,870],{"class":219}," Shape",[209,872,224],{"class":223},[209,874,875,877],{"class":211,"line":227},[209,876,433],{"class":219},[209,878,436],{"class":236},[209,880,881,883,886],{"class":211,"line":244},[209,882,254],{"class":215},[209,884,885],{"class":219}," default",[209,887,508],{"class":223},[209,889,890,892,894,897],{"class":211,"line":251},[209,891,315],{"class":215},[209,893,482],{"class":236},[209,895,896],{"class":223},"()          ",[209,898,899],{"class":240},"# builds the right subtype\n",[209,901,902],{"class":211,"line":263},[209,903,248],{"emptyLinePlaceholder":247},[209,905,906,908],{"class":211,"line":280},[209,907,433],{"class":219},[209,909,765],{"class":236},[209,911,912,914,917],{"class":211,"line":285},[209,913,254],{"class":215},[209,915,916],{"class":219}," default_bad",[209,918,919],{"class":223},"():\n",[209,921,922,924,927],{"class":211,"line":299},[209,923,315],{"class":215},[209,925,926],{"class":223}," Shape()        ",[209,928,929],{"class":240},"# always Shape, never the subclass\n",[209,931,932],{"class":211,"line":312},[209,933,248],{"emptyLinePlaceholder":247},[209,935,936,938,941,943,946],{"class":211,"line":324},[209,937,216],{"class":215},[209,939,940],{"class":219}," Circle",[209,942,462],{"class":223},[209,944,945],{"class":219},"Shape",[209,947,606],{"class":223},[209,949,950],{"class":211,"line":329},[209,951,611],{"class":215},[209,953,954],{"class":211,"line":346},[209,955,248],{"emptyLinePlaceholder":247},[209,957,958,960,963],{"class":211,"line":519},[209,959,620],{"class":236},[209,961,962],{"class":223},"(Circle.default())        ",[209,964,965],{"class":240},"# Circle  — correct\n",[209,967,968,970,973],{"class":211,"line":530},[209,969,620],{"class":236},[209,971,972],{"class":223},"(Circle.default_bad())    ",[209,974,975],{"class":240},"# Shape   — wrong\n",[15,977,978,981,982,984,985,198],{},[19,979,980],{},"Rule of thumb:"," any factory or constructor method that subclasses might inherit should\nbe a ",[45,983,47],{},", never a ",[45,986,52],{},[10,988,990],{"id":989},"the-decision-rule","The decision rule",[15,992,993],{},"Answer two questions:",[995,996,997,1007,1015],"ol",{},[998,999,1000,1006],"li",{},[19,1001,1002,1003,1005],{},"Does the method need access to ",[45,1004,68],{}," (instance state)?","\n→ Instance method.",[998,1008,1009,1012,1013,198],{},[19,1010,1011],{},"Does the method need to create instances of the correct (sub)class or access\nclass-level state, but not a specific instance?","\n→ ",[45,1014,47],{},[998,1016,1017,1012,1025,198],{},[19,1018,1019,1020,107,1022,1024],{},"Is the method a utility helper that doesn't touch ",[45,1021,68],{},[45,1023,74],{}," at all?",[45,1026,52],{},[200,1028,1030],{"className":202,"code":1029,"language":204,"meta":205,"style":205},"class User:\n    role = \"user\"                          # class attribute\n\n    def __init__(self, name, email):\n        self.name = name                   # instance attribute\n        self.email = email\n\n    def greet(self):                       # instance method — uses self\n        return f\"Hi, I'm {self.name}\"\n\n    @classmethod\n    def from_dict(cls, data):             # classmethod — factory from dict\n        return cls(data[\"name\"], data[\"email\"])\n\n    @staticmethod\n    def is_valid_email(email):            # staticmethod — pure utility\n        return \"@\" in email and \".\" in email\n",[45,1031,1032,1041,1054,1058,1067,1082,1094,1098,1111,1133,1137,1143,1156,1177,1181,1187,1200],{"__ignoreMap":205},[209,1033,1034,1036,1039],{"class":211,"line":212},[209,1035,216],{"class":215},[209,1037,1038],{"class":219}," User",[209,1040,224],{"class":223},[209,1042,1043,1046,1048,1051],{"class":211,"line":227},[209,1044,1045],{"class":223},"    role ",[209,1047,233],{"class":215},[209,1049,1050],{"class":471}," \"user\"",[209,1052,1053],{"class":240},"                          # class attribute\n",[209,1055,1056],{"class":211,"line":244},[209,1057,248],{"emptyLinePlaceholder":247},[209,1059,1060,1062,1064],{"class":211,"line":251},[209,1061,254],{"class":215},[209,1063,257],{"class":236},[209,1065,1066],{"class":223},"(self, name, email):\n",[209,1068,1069,1071,1074,1076,1079],{"class":211,"line":263},[209,1070,266],{"class":236},[209,1072,1073],{"class":223},".name ",[209,1075,233],{"class":215},[209,1077,1078],{"class":223}," name                   ",[209,1080,1081],{"class":240},"# instance attribute\n",[209,1083,1084,1086,1089,1091],{"class":211,"line":280},[209,1085,266],{"class":236},[209,1087,1088],{"class":223},".email ",[209,1090,233],{"class":215},[209,1092,1093],{"class":223}," email\n",[209,1095,1096],{"class":211,"line":285},[209,1097,248],{"emptyLinePlaceholder":247},[209,1099,1100,1102,1105,1108],{"class":211,"line":299},[209,1101,254],{"class":215},[209,1103,1104],{"class":219}," greet",[209,1106,1107],{"class":223},"(self):                       ",[209,1109,1110],{"class":240},"# instance method — uses self\n",[209,1112,1113,1115,1118,1121,1124,1127,1130],{"class":211,"line":312},[209,1114,315],{"class":215},[209,1116,1117],{"class":215}," f",[209,1119,1120],{"class":471},"\"Hi, I'm ",[209,1122,1123],{"class":236},"{self",[209,1125,1126],{"class":223},".name",[209,1128,1129],{"class":236},"}",[209,1131,1132],{"class":471},"\"\n",[209,1134,1135],{"class":211,"line":324},[209,1136,248],{"emptyLinePlaceholder":247},[209,1138,1139,1141],{"class":211,"line":329},[209,1140,433],{"class":219},[209,1142,436],{"class":236},[209,1144,1145,1147,1150,1153],{"class":211,"line":346},[209,1146,254],{"class":215},[209,1148,1149],{"class":219}," from_dict",[209,1151,1152],{"class":223},"(cls, data):             ",[209,1154,1155],{"class":240},"# classmethod — factory from dict\n",[209,1157,1158,1160,1162,1165,1168,1171,1174],{"class":211,"line":519},[209,1159,315],{"class":215},[209,1161,482],{"class":236},[209,1163,1164],{"class":223},"(data[",[209,1166,1167],{"class":471},"\"name\"",[209,1169,1170],{"class":223},"], data[",[209,1172,1173],{"class":471},"\"email\"",[209,1175,1176],{"class":223},"])\n",[209,1178,1179],{"class":211,"line":530},[209,1180,248],{"emptyLinePlaceholder":247},[209,1182,1183,1185],{"class":211,"line":540},[209,1184,433],{"class":219},[209,1186,765],{"class":236},[209,1188,1189,1191,1194,1197],{"class":211,"line":545},[209,1190,254],{"class":215},[209,1192,1193],{"class":219}," is_valid_email",[209,1195,1196],{"class":223},"(email):            ",[209,1198,1199],{"class":240},"# staticmethod — pure utility\n",[209,1201,1202,1204,1207,1210,1213,1216,1219,1221],{"class":211,"line":560},[209,1203,315],{"class":215},[209,1205,1206],{"class":471}," \"@\"",[209,1208,1209],{"class":215}," in",[209,1211,1212],{"class":223}," email ",[209,1214,1215],{"class":215},"and",[209,1217,1218],{"class":471}," \".\"",[209,1220,1209],{"class":215},[209,1222,1093],{"class":223},[10,1224,1226],{"id":1225},"recap","Recap",[15,1228,1229,1230,1233,1234,1236,1237,1233,1241,1243,1244,1247,1248,1252,1253,1255],{},"An ",[19,1231,1232],{},"instance method"," takes ",[45,1235,68],{}," and is the right default for any per-object behaviour.\nA ",[19,1238,1239],{},[45,1240,47],{},[45,1242,74],{}," — use it for alternative constructors and class-level\nlogic, always with ",[45,1245,1246],{},"cls(...)"," rather than the hard-coded class name so subclasses get the\nright type. A ",[19,1249,1250],{},[45,1251,52],{}," takes nothing implicit — use it for utility helpers that\nbelong in the class namespace but genuinely don't interact with any instance or class\nstate. When in doubt between the two non-instance options, prefer ",[45,1254,47],{}," if there's\nany chance a subclass will call it.",[1257,1258,1259],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}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":205,"searchDepth":227,"depth":227,"links":1261},[1262,1263,1264,1265,1267,1269,1270,1271],{"id":12,"depth":227,"text":13},{"id":25,"depth":227,"text":26},{"id":185,"depth":227,"text":186},{"id":364,"depth":227,"text":1266},"@classmethod — the alternative constructor pattern",{"id":666,"depth":227,"text":1268},"@staticmethod — a regular function inside the class namespace",{"id":848,"depth":227,"text":849},{"id":989,"depth":227,"text":990},{"id":1225,"depth":227,"text":1226},"Python @classmethod vs @staticmethod vs instance method explained — what each receives as its first argument, the alternative-constructor pattern, subclass safety, and the decision rule that makes the right choice obvious.","medium","md","Python",{},"\u002Fblog\u002Fpython-classmethod-vs-staticmethod-vs-instance-method",{"title":5,"description":1272},"blog\u002Fpython-classmethod-vs-staticmethod-vs-instance-method","classmethod vs staticmethod vs instance method","Object-Oriented Programming","oop","2026-06-21","Q2M1zWlL_r4351T6okN-RXjVuGvuolvtMC2VKMKxfOI",1782244087949]