{"id":105,"date":"2025-05-23T03:09:17","date_gmt":"2025-05-23T03:09:17","guid":{"rendered":"https:\/\/www.alerainfotech.com\/?p=105"},"modified":"2025-05-23T03:09:43","modified_gmt":"2025-05-23T03:09:43","slug":"can-python-have-two-price-methods-understanding-property-overloading-and-how-python-gets-it-right","status":"publish","type":"post","link":"https:\/\/www.alerainfotech.com\/home\/2025\/05\/23\/can-python-have-two-price-methods-understanding-property-overloading-and-how-python-gets-it-right\/","title":{"rendered":"Can Python Have Two\u00a0price()\u00a0Methods? Understanding\u00a0@property, Overloading, and How Python Gets It Right"},"content":{"rendered":"\n<p>If you&#8217;re coming from Java, C++, or C#, one of the first things you&#8217;ll notice in Python is this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>&#8220;Wait&#8230; how can I define&nbsp;<code>def price(self)<\/code>&nbsp;and&nbsp;<code>def price(self, value)<\/code>&nbsp;in the same class? Isn&#8217;t that illegal?&#8221;<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p>Yes \u2014&nbsp;<strong>in Java, that\u2019s method overloading<\/strong>.<br>But in Python? Well&#8230;&nbsp;<strong>it depends<\/strong>.<\/p>\n\n\n\n<p>In this article, we\u2019ll walk through:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>How method overloading works (and doesn\u2019t work) in Python<\/li>\n\n\n\n<li>What the\u00a0<code>@property<\/code>\u00a0decorator really does<\/li>\n\n\n\n<li>Why\u00a0<code>@price.setter<\/code>\u00a0doesn\u2019t overwrite the original method<\/li>\n\n\n\n<li>And how this turns into one of Python\u2019s most elegant features:\u00a0<strong>property binding<\/strong><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udd0d Let\u2019s Start with the Problem<\/h2>\n\n\n\n<p>Here\u2019s what&nbsp;<strong>doesn\u2019t work<\/strong>&nbsp;in Python:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>class Product:<br>    def price(self):<br>        return 100<br><br>    def price(self, value):  # \u274c This will override the first one<br>        self._price = value<br><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\u274c Output:<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">bashCopyEdit<code>TypeError: price() missing 1 required positional argument: 'value'\n<\/code><\/pre>\n\n\n\n<p>That\u2019s because Python&nbsp;<strong>does not support traditional method overloading<\/strong>. The second method with the same name (<code>price<\/code>) completely&nbsp;<strong>overwrites<\/strong>&nbsp;the first.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udeab So How Do We Add a Setter?<\/h2>\n\n\n\n<p>In Java:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>public int getPrice() { return this.price; }<br>public void setPrice(int value) { this.price = value; }<br><\/code><\/pre>\n\n\n\n<p>In Python, we use the&nbsp;<code>@property<\/code>&nbsp;decorator:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>class Product:<br>    def __init__(self):<br>        self._price = 0<br><br>    @property<br>    def price(self):<br>        return self._price<br><br>    @price.setter<br>    def price(self, value):<br>        self._price = value<br><\/code>   <\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\uddea What\u2019s Happening Internally?<\/h2>\n\n\n\n<p>When you write:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>@property<br>def price(self):<br>    ...<br><\/code><\/pre>\n\n\n\n<p>Python turns&nbsp;<code>price()<\/code>&nbsp;into a&nbsp;<strong><code>property<\/code>&nbsp;object<\/strong>, not a method.<\/p>\n\n\n\n<p>Then when you write:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>@price.setter<br>def price(self, value):<br>    ...<br><\/code><\/pre>\n\n\n\n<p>You&#8217;re not defining a&nbsp;<strong>new method<\/strong>&nbsp;called&nbsp;<code>price<\/code>&nbsp;\u2014 you&#8217;re telling Python:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201cHey, add this as the&nbsp;<code>setter<\/code>&nbsp;for the existing property called&nbsp;<code>price<\/code>.\u201d<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde0 No Overloading, Just Property Binding<\/h2>\n\n\n\n<p>Here\u2019s what Python does under the hood:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>price = property(get_price)           # @property<br>price = price.setter(set_price)      # @price.setter<br><\/code><\/pre>\n\n\n\n<p>So both the getter and the setter are&nbsp;<strong>part of the same property object<\/strong>&nbsp;\u2014 there\u2019s&nbsp;<strong>no method conflict<\/strong>, no overwriting.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2705 Final Usage<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>p = Product()<br>p.price = 99         # Calls setter<br>print(p.price)       # Calls getter<br><\/code><\/pre>\n\n\n\n<p>The object&nbsp;<strong>looks and behaves like it has a real attribute<\/strong>, but under the hood it&#8217;s calling&nbsp;<code>getter<\/code>&nbsp;and&nbsp;<code>setter<\/code>&nbsp;logic.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\u2705 Visual Summary<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>class Product:<br>    @property<br>    def price(self):         # READ<br>        return self._price<br><br>    @price.setter<br>    def price(self, value):  # WRITE<br>        self._price = value<br><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Operation<\/th><th>What Happens<\/th><\/tr><\/thead><tbody><tr><td><code>p.price<\/code><\/td><td>\u279c calls&nbsp;<code>price()<\/code>&nbsp;getter<\/td><\/tr><tr><td><code>p.price = x<\/code><\/td><td>\u279c calls&nbsp;<code>price()<\/code>&nbsp;setter<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde9 Bonus: Adding a Deleter<\/h2>\n\n\n\n<p>You can even add a deleter!<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>@price.deleter<br>def price(self):<br>    del self._price<br><\/code><\/pre>\n\n\n\n<p>Now you can do:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>del p.price<br><\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udeab Why Not Just Write&nbsp;<code>@setter<\/code>?<\/h2>\n\n\n\n<p>This is a common beginner mistake:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>@setter  # \u274c INVALID<br>def price(self, value): ...<br><\/code><\/pre>\n\n\n\n<p>Python wouldn\u2019t know&nbsp;<strong>which property this setter is for<\/strong>. That&#8217;s why you write:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><code>@price.setter<br><\/code><\/pre>\n\n\n\n<p>You&#8217;re explicitly saying:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;This is the setter for the&nbsp;<code>price<\/code>&nbsp;property.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83d\udccc Key Takeaways<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 Python does\u00a0<strong>not support method overloading<\/strong><\/li>\n\n\n\n<li>\u2705\u00a0<code>@property<\/code>\u00a0lets you\u00a0<strong>simulate fields with controlled access<\/strong><\/li>\n\n\n\n<li>\u2705\u00a0<code>@price.setter<\/code>\u00a0and\u00a0<code>@price.deleter<\/code>\u00a0are\u00a0<strong>not new methods<\/strong>, but\u00a0<strong>extensions of the same property<\/strong><\/li>\n\n\n\n<li>\u2705 You can\u2019t define\u00a0<code>price()<\/code>\u00a0and\u00a0<code>price(value)<\/code>\u00a0as two separate methods \u2014 but\u00a0<code>@property<\/code>\u00a0lets you achieve the same goal cleanly<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83e\udde0 Real-Life Use Cases<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Use Case<\/th><th>Why Use&nbsp;<code>@property<\/code><\/th><\/tr><\/thead><tbody><tr><td>Validation before assignment<\/td><td>e.g.,&nbsp;<code>if value &lt; 0: raise...<\/code><\/td><\/tr><tr><td>Making attributes read-only<\/td><td>No setter<\/td><\/tr><tr><td>Lazy computation<\/td><td>Compute on-demand in getter<\/td><\/tr><tr><td>Backward compatibility<\/td><td>Turn methods into fields later<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ud83c\udfc1 Final Thoughts<\/h2>\n\n\n\n<p>What looks like method overloading in Python is actually something more elegant:&nbsp;<strong>binding multiple behaviors to a single property<\/strong>&nbsp;using decorators.<\/p>\n\n\n\n<p>The&nbsp;<code>@property<\/code>&nbsp;pattern is clean, readable, and Pythonic. And unlike Java, you can make your class interface&nbsp;<strong>look like attributes<\/strong>&nbsp;while keeping full control over logic.<\/p>\n\n\n\n<p>So no \u2014 Python doesn\u2019t support method overloading.<br>But thanks to&nbsp;<code>@property<\/code>,&nbsp;<strong>you don\u2019t even need it<\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;re coming from Java, C++, or C#, one of the first things you&#8217;ll notice in Python is this: &#8220;Wait&#8230; how can I define&nbsp;def price(self)&nbsp;and&nbsp;def price(self, value)&nbsp;in the same class? Isn&#8217;t that illegal?&#8221; Yes \u2014&nbsp;in Java, that\u2019s method overloading.But in Python? Well&#8230;&nbsp;it depends. In this article, we\u2019ll walk through: \ud83d\udd0d Let\u2019s Start with the Problem [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-105","post","type-post","status-publish","format-standard","hentry","category-python-blog"],"_links":{"self":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/105","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/comments?post=105"}],"version-history":[{"count":2,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/105\/revisions"}],"predecessor-version":[{"id":107,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/posts\/105\/revisions\/107"}],"wp:attachment":[{"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/media?parent=105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/categories?post=105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.alerainfotech.com\/home\/wp-json\/wp\/v2\/tags?post=105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}