[{"data":1,"prerenderedAt":74},["ShallowReactive",2],{"qa-\u002Fpython\u002Foop\u002Fmethods-properties":3},{"page":4,"siblings":53,"blog":44},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":44,"seo":45,"seoDescription":46,"stem":47,"subtopic":48,"topic":49,"topicSlug":50,"updated":51,"__hash__":52},"qa\u002Fpython\u002Foop\u002Fmethods-properties.md","Methods Properties",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Python","python",{},true,4,"\u002Fpython\u002Foop\u002Fmethods-properties",[23,27,31,35,39],{"id":24,"difficulty":14,"q":25,"a":26},"instance-class-static-methods","What is the difference between an instance method, @classmethod, and @staticmethod?","An **instance method** takes `self` and operates on a specific object. A\n**`@classmethod`** takes `cls` (the class, not an instance) and works on\n**class-level state** or builds instances. A **`@staticmethod`** takes\n**neither** — it's a plain function namespaced inside the class, with no access\nto instance or class state.\n\n```python\nclass Pizza:\n    base_price = 10\n    def __init__(self, toppings):\n        self.toppings = toppings\n    def total(self):                    # instance method — uses self\n        return self.base_price + len(self.toppings)\n    @classmethod\n    def margherita(cls):                # classmethod — uses cls\n        return cls([\"mozzarella\", \"basil\"])\n    @staticmethod\n    def is_valid_topping(name):         # staticmethod — no self\u002Fcls\n        return name.isalpha()\n\nPizza.is_valid_topping(\"ham\")   # True — no instance needed\nPizza.margherita().total()      # 12\n```\n\nUse an instance method for per-object behavior, a classmethod for\nclass-aware logic (e.g. alternative constructors), and a staticmethod for a\nrelated helper that happens to live on the class.\n",{"id":28,"difficulty":14,"q":29,"a":30},"classmethod-constructor","How do you use a classmethod as an alternative constructor?","A classmethod receives `cls`, so it can **build and return a new instance** from\na different input format — giving you multiple named constructors beyond\n`__init__`. Using `cls` (not the hard-coded class name) means **subclasses get\nthe right type** automatically.\n\n```python\nclass Date:\n    def __init__(self, year, month, day):\n        self.year, self.month, self.day = year, month, day\n    @classmethod\n    def from_string(cls, text):\n        y, m, d = map(int, text.split(\"-\"))\n        return cls(y, m, d)             # returns the (sub)class instance\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-18\")   # alternative constructor\nDate.today()\n```\n\nThis is the idiomatic Python pattern (`dict.fromkeys`, `datetime.fromtimestamp`)\nfor \"make one of these, but from X\" — clearer than overloading `__init__` with\nflags.\n",{"id":32,"difficulty":14,"q":33,"a":34},"property-getter-setter","How does @property work with a getter and setter?","`@property` turns a method into a **managed attribute** — you access it like\n`obj.x` (no parentheses), but a method runs behind the scenes. The matching\n`@x.setter` runs on assignment, letting you add **validation** without changing\nthe public interface.\n\n```python\nclass Account:\n    def __init__(self, balance):\n        self._balance = balance         # \"private\" backing field\n    @property\n    def balance(self):                  # getter — runs on read\n        return self._balance\n    @balance.setter\n    def balance(self, value):           # setter — runs on write\n        if value \u003C 0:\n            raise ValueError(\"balance cannot be negative\")\n        self._balance = value\n\nacc = Account(100)\nacc.balance          # 100 — looks like an attribute, calls the getter\nacc.balance = 50     # calls the setter (validated)\nacc.balance = -1     # ValueError\n```\n\nThe convention is a `_name` backing attribute behind a public property. Omit the\nsetter to make the property read-only.\n",{"id":36,"difficulty":14,"q":37,"a":38},"why-properties-over-getters","Why do properties beat Java-style getter\u002Fsetter methods?","In Python you **start with a plain attribute** and only convert it to a\n`@property` later **if** you need validation or computation — **without changing\nthe call sites**. So you avoid the Java habit of pre-emptively writing\n`getX()`\u002F`setX()` \"just in case\". The public API stays `obj.x`.\n\n```python\n# Start simple — public attribute:\nclass Circle:\n    def __init__(self, radius):\n        self.radius = radius\n\nc = Circle(5)\nc.radius            # direct access — no ceremony\n\n# Later, add validation transparently — callers don't change:\nclass Circle:\n    def __init__(self, radius):\n        self.radius = radius\n    @property\n    def radius(self):\n        return self._radius\n    @radius.setter\n    def radius(self, value):\n        if value \u003C= 0:\n            raise ValueError(\"radius must be positive\")\n        self._radius = value\n```\n\nThis is the \"uniform access principle\": callers can't tell whether `obj.x` is a\nstored value or computed. Don't write getters\u002Fsetters upfront — reach for a\nproperty only when behavior is needed.\n",{"id":40,"difficulty":41,"q":42,"a":43},"computed-readonly-properties","easy","How do you create a computed or read-only property?","A property with **only a getter** (no setter) is **read-only** — assigning to it\nraises `AttributeError`. A **computed property** derives its value from other\nattributes on each access, so it stays in sync automatically rather than being\nstored.\n\n```python\nclass Rectangle:\n    def __init__(self, width, height):\n        self.width = width\n        self.height = height\n    @property\n    def area(self):                 # computed — derived on each read\n        return self.width * self.height\n\nr = Rectangle(3, 4)\nr.area           # 12 — computed\nr.width = 5\nr.area           # 20 — automatically reflects the change\nr.area = 99      # AttributeError — read-only (no setter)\n```\n\nFor an expensive computation you only want to run once, use\n`functools.cached_property` instead, which caches the result on first access.\nUse a plain read-only property for cheap derived values.\n",null,{"description":11},"Python interview questions on instance vs classmethod vs staticmethod, classmethods as alternative constructors, the @property getter\u002Fsetter, why properties beat Java-style accessors, and computed\u002Fread-only properties.","python\u002Foop\u002Fmethods-properties","Methods & Properties","Object-Oriented Programming","oop","2026-06-18","EZTMeTHDuvwapkor3EW7aAeDQlUzCDXBSwLIpBJ6zww",[54,58,61,65,66,70],{"subtopic":55,"path":56,"order":57},"Inheritance & the MRO","\u002Fpython\u002Foop\u002Finheritance",1,{"subtopic":59,"path":60,"order":12},"Classes, Instances & __init__","\u002Fpython\u002Foop\u002Fclasses",{"subtopic":62,"path":63,"order":64},"Dunder \u002F Magic Methods","\u002Fpython\u002Foop\u002Fdunder-methods",3,{"subtopic":48,"path":21,"order":20},{"subtopic":67,"path":68,"order":69},"Dataclasses & __slots__","\u002Fpython\u002Foop\u002Fdataclasses-slots",5,{"subtopic":71,"path":72,"order":73},"Abstract Base Classes & Protocols","\u002Fpython\u002Foop\u002Fabc-protocols",6,1781808680178]