Sick Gaming
[Tut] Python classmethod() - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: Python (https://www.sickgaming.net/forum-83.html)
+--- Thread: [Tut] Python classmethod() (/thread-98791.html)



[Tut] Python classmethod() - xSicKxBot - 12-17-2020

Python classmethod()

<div><p class="has-pale-cyan-blue-background-color has-background">Python’s built-in function <code><code>classmethod</code>()</code> prefixes a method definition in a class as an annotation <code>@classmethod</code>. This annotation transforms a normal instance method into a class method. The difference between class and instance method is that Python passes the class itself as a first implicit argument of the method rather than the instance on which it is called. </p>
<p>In this tutorial, I’ll show you one of Python’s little-known secrets that separate the intermediates from the experts: class methods. You may know the difference between an instance method and a class method conceptually. (If you don’t, this tutorial is for you.) But do you also know how to create a class method in Python? If not, read on, because this tutorial will show you!</p>
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<div class="wp-block-embed__wrapper">
<div class="ast-oembed-container"><iframe title="Python classmethod() | A Helpful Guide" width="1400" height="788" src="https://www.youtube.com/embed/IBjwNReqxDc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
</div>
</figure>
<h2>Syntax Class Method</h2>
<pre class="wp-block-preformatted"><strong>Syntax</strong>: <code>classmethod(function)</code> # &lt;--- This is considered unpythonic
<code>@classmethod</code> # &lt;--- As a prefix before the used method</pre>
<p>The most Pythonic way to declare a class method is the following decorator syntax:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class C: @classmethod def f(cls, arg1, arg2, ...): None</pre>
<h2>How to Call a Class Method?</h2>
<p>There are two ways of using a class method: </p>
<ul>
<li>You can call it on a class such as <code>C.f(arg1, arg2, ...)</code>, or</li>
<li>You can call it on an instance such as <code>C().f(arg1, arg2, ...)</code>. </li>
</ul>
<p>Note that Python implicitly passes the class itself—in Python, everything including a class is an object—as a first argument. Roughly speaking, if you call <code>C.f(arg1, arg2, ...)</code>, Python really runs <code>f(<strong>C</strong>, arg1, arg2, ...)</code> with the class object passed as a first argument.</p>
<h2>Example Class Method</h2>
<p>When to use a class method? You’ll find that class methods are often used in a factory pattern. A factory pattern is one of the most popular software development patterns: a so-called factory method creates new instances of a certain type. It is responsible for actually creating the instances from a given class definition.</p>
<p>In the following example, you define a class <code>Coffee</code> that represents a real coffee serving in a coffee bar. There are many specialities such as Cappuccino (80% milk, 20% coffee), Espresso Macchiato (30% milk, 70% coffee), and Latte Macchiato (95% milk, 5% coffee). </p>
<p>You use the class methods to allow users to conveniently call factory methods instead of setting the milk level themselves. Instead of calling <code>Coffee(80, 20, 'Arrabica')</code>, a user can just call <code>cappuccino()</code> to create the same instance of the class <code>Coffee</code>. This simplifies the creation of new instances and can improve the readability and usability of your code:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Coffee: def __init__(self, milk, beans): self.milk = milk # percentage self.coffee = 100-milk # percentage self.beans = beans def __repr__(self): return f'Milk={self.milk}% Coffee={self.coffee}% Beans={self.beans}' @classmethod def cappuccino(cls): return clf(80, 'Arrabica') @classmethod def espresso_macchiato(cls): return cls(30, 'Robusta') @classmethod def latte(cls): return cls(95, 'Arrabica') print(Coffee.cappuccino())
print(Coffee.espresso_macchiato())
print(Coffee.latte())
</pre>
<p>The three lines of output are:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Milk=80% Coffee=20% Beans=Arrabica
Milk=30% Coffee=70% Beans=Robusta
Milk=95% Coffee=5% Beans=Arrabica</pre>
<p>You can run this example in our interactive Jupyter Notebook:</p>
<h2>Interactive Example Class Method</h2>
<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://colab.research.google.com/drive/1zjaO17_F_0KUQfSHJojAF0mZ5ZqxD6VL?usp=sharing" target="_blank" rel="noopener noreferrer"><img loading="lazy" width="1024" height="704" src="https://blog.finxter.com/wp-content/uploads/2020/12/image-47-1024x704.png" alt="" class="wp-image-18655" srcset="https://blog.finxter.com/wp-content/uploads/2020/12/image-47-1024x704.png 1024w, https://blog.finxter.com/wp-content/uploads/2020/12/image-47-300x206.png 300w, https://blog.finxter.com/wp-content/uploads/2020/12/image-47-768x528.png 768w, https://blog.finxter.com/wp-content/uploads/2020/12/image-47-150x103.png 150w, https://blog.finxter.com/wp-content/uploads/2020/12/image-47.png 1055w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption><a href="https://colab.research.google.com/drive/1zjaO17_F_0KUQfSHJojAF0mZ5ZqxD6VL?usp=sharing" target="_blank" rel="noreferrer noopener" title="https://colab.research.google.com/drive/1zjaO17_F_0KUQfSHJojAF0mZ5ZqxD6VL?usp=sharing">Click to run code (interactive Jupyter Notebook)</a></figcaption></figure>
</div>
<p><em><strong>Exercise</strong>: Can you create another coffee specialty?</em></p>
<h2>Class Method Naming Convention: cls vs self</h2>
<p>In the previous example, you’ve seen the naming convention of the first argument of a class method: it’s the three characters <code>cls</code>—short for “class”, but we cannot take this because <code>class</code> is a <a href="https://blog.finxter.com/python-cheat-sheet/" title="Python Beginner Cheat Sheet: 19 Keywords Every Coder Must Know" target="_blank" rel="noreferrer noopener">reserved keyword</a>. You can use any name you want but using the name <code>cls</code> is the expected convention and it’s highly recommended. The naming convention of the first implicit argument of instance methods is the name <code>self</code>. </p>
<p><strong>Related Article:</strong> <a href="https://blog.finxter.com/self-in-python/" target="_blank" rel="noreferrer noopener" title="Python Self — An Interactive Guide with Video">Self in Python</a></p>
<h2>Class Method is a Function Decorator</h2>
<p>Decorators help to add functionality to existing code without having to modify the code itself. Decorators are so-called because they decorate code, they do not modify the code, but they make the code do different things using decoration. Now that we have understood closures, we can work our way step by step to understanding and using decorators.</p>
<p>The <code>@classmethod</code> is a function decorator. It’s short for calling <code>classmethod(m)</code> for the method <code>m</code> that you would decorate. </p>
<p>Here’s the same simplified coffee example without using a decorator and by using classmethod() instead:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Coffee: def __init__(self, milk, beans): self.milk = milk # percentage self.coffee = 100-milk # percentage self.beans = beans def __repr__(self): return f'Milk={self.milk}% Coffee={self.coffee}% Beans={self.beans}' def cappuccino(cls): return cls(80, 'Arrabica') Coffee.cappuccino = classmethod(Coffee.cappuccino)
print(Coffee.cappuccino())</pre>
<p>The output is the same:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Milk=80% Coffee=20% Beans=Arrabica</pre>
<p>However, this is not the recommended way—use a decorator with the @ annotation instead!</p>
<p><strong>Related Article:</strong> <a href="https://blog.finxter.com/closures-and-decorators-in-python/" target="_blank" rel="noreferrer noopener" title="Closures and Decorators in Python">Decorators</a></p>
<h2>Class Method vs Instance Method</h2>
<p class="has-pale-cyan-blue-background-color has-background">If you don’t use the <code>@classmethod</code> annotator, you obtain an instance method per default. The instance method requires that the first argument <code>self</code> is a reference to the instance itself on which the method is called. The class method expects a reference to the class, not the instance, as a first argument <code>cls</code>. Thus, the difference between class and instance methods is that Python passes the class rather than the instance (object) as a first implicit argument.</p>
<p>Here’s a minimal example of a class and an instance method:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class C: @classmethod def f(cls): None # instance method def g(self): None # call class method:
C.f() # call instance method:
C().g()
</pre>
<p>There are two ways of using a class method: </p>
<ul>
<li>You can call it on a class such as <code>C.f(arg1, arg2, ...)</code>, or</li>
<li>You can call it on an instance such as <code>C().f(arg1, arg2, ...)</code>. </li>
</ul>
<p>But there’s only one way of using an instance method:</p>
<ul>
<li>You can call it on an instance such as <code>C().g()</code>.</li>
</ul>
<h2>Class Method vs Static Method</h2>
<p class="has-pale-cyan-blue-background-color has-background">You may know static methods from programming languages such as C++ or Java. They’re methods that exist independently of whether or not you created an instance of the class. That’s why they don’t use any instance variable in the method body. If you want to use a static method in Python, you need to use the <code>@staticmethod</code> annotation rather than the <code>@classmethod</code> annotation. The difference is that static methods don’t expect a reference to either the instance or the class as an implied first argument. </p>
<p>Here’s an example comparing class methods, instance methods, and static methods:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class C: @classmethod def f(cls): None # instance method def g(self): None @staticmethod def h(): None # call class method:
C.f() # call instance method:
C().g() # call static method:
C.h()
</pre>
<h2>Summary</h2>
<p>Python’s built-in function <code><code>classmethod</code>()</code> prefixes a method definition in a class as an annotation <code>@classmethod</code>. </p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class C: @classmethod def f(cls, arg1, arg2, ...): None</pre>
<p>This annotation transforms a normal instance method into a class method. </p>
<p>The difference between class and instance method is that Python passes the class itself as a first implicit argument of the method rather than the instance on which it is called:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class C: @classmethod def f(cls, arg1, arg2, ...): None # instance method def g(self, arg1, arg2, ...): None</pre>
<hr class="wp-block-separator"/>
<p>Do you want to boost your Python skills in a fun and easy-to-consume way? Consider the following resources and become a master coder!</p>
<h2>Where to Go From Here?</h2>
<p>Enough theory, let’s get some practice!</p>
<p>To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?</p>
<p><strong>Practice projects is how you sharpen your saw in coding!</strong></p>
<p>Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?</p>
<p>Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.</p>
<p>Join my free webinar <a rel="noreferrer noopener" href="https://blog.finxter.com/webinar-freelancer/" target="_blank">“How to Build Your High-Income Skill Python”</a> and watch how I grew my coding business online and how you can, too—from the comfort of your own home.</p>
<p><a href="https://blog.finxter.com/webinar-freelancer/" target="_blank" rel="noreferrer noopener">Join the free webinar now!</a></p>
<p>The post <a href="https://blog.finxter.com/python-classmethod/" target="_blank" rel="noopener noreferrer">Python classmethod()</a> first appeared on <a href="https://blog.finxter.com/" target="_blank" rel="noopener noreferrer">Finxter</a>.</p>
</div>


https://www.sickgaming.net/blog/2020/12/16/python-classmethod/