avatarYang Zhou

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3458

Abstract

e namespace by the class but we can access the class namespace by its instance.</p><p id="0097">There is an interesting problem: if the class attribute and instance attribute have the same name, what will happen?</p><figure id="51ef"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*Wik3W6cQEdNoG7wk"><figcaption>Photo by <a href="https://unsplash.com/@andremouton?utm_source=medium&amp;utm_medium=referral">Andre Mouton</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p id="a027">Let’s look an example:</p> <figure id="a826"> <div> <div>

            <iframe class="gist-iframe" src="/gist/ZhouYang1993/e038126c3362f209b3e10b1e80202294.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="75ae">As shown above, namespace of instance has priority over namespace of class, so the <code>guy.name</code> is “Jack” at the beginning. After <code>del guy.name</code> , we don’t have <code>name</code> attribute in instance namespace, if we use the same name again, the class attributes will be accessed.</p><p id="33a0">My suggestion is: when writing a program, <b>do not use the same name for instance attributes and class attributes. </b>It could result in unintended consequences because sometimes we could forget which type of attribute we are using if their names are the same.</p><p id="c8a1">By the way, Yang is really an handsome guy. If you don’t believe it, please look the example code again. 😄</p><h1 id="94de">Change Values of Class Attribute</h1><p id="9c80">The rules are:</p><ul><li>If we change the value of a class attribute by the class, we will get the new value of course when we access it by instances.</li><li>However, if we change the value of a class attribute by an instance, the result is a little complicated, two different consequences for two situations:</li></ul><ol><li>If this attribute is immutable, the attribute will become a instance attribute within current instance, the value changes will not affect other instances and the class.</li></ol>
    <figure id="a472">
        <div>
          <div>
            
            <iframe class="gist-iframe" src="/gist/ZhouYang1993/a0b9767c4b88f80774ba4820cfa955bb.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="d8fd">2. If this class attribute is mutable, the results depend on how we change it.</p>
    <figure id="e4a9">
        <div>
          <div>
            
            <iframe class="gist-iframe" src="/gist/ZhouYang1993/337152ac4296770a68c0358df9e03f6f.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="c876">My suggestion is: <b>always define class attributes as immutable objects to avoid unintended results.</b> For this example, we can define like this:</p><div id="003c"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">MyClass</span>(object):
data = <span class="hljs-title class_">None</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span c

Options

lass="hljs-params"><span class="hljs-variable language_">self</span>, value</span>): <span class="hljs-variable language_">self</span>.instance_data = value</pre></div><figure id="0ec3"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*q4dIjAkmts-MLBn2"><figcaption>Photo by <a href="https://unsplash.com/@jentheodore?utm_source=medium&amp;utm_medium=referral">Jen Theodore</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p id="9d9b">We define the <code>data</code> as <code>None</code> rather than list.</p><p id="0fa9">It looks like just a minor issue. But, actually it will avoid lots of hidden bugs in a big project. If you are in an interview, how you define the data will show whether you are <i>Senior Python Developer</i> or not.</p><h1 id="a5de">When to Use Class Attribute</h1><ol><li>Define some constant or default value as class attribute which can use for every instances.</li></ol><div id="a151"><pre><span class="hljs-keyword">class</span> <span class="hljs-title class_">Circle</span>(object): <span class="hljs-variable constant_">PI</span> = <span class="hljs-number">3.14</span>

<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span>, value</span>):
    <span class="hljs-variable language_">self</span>.radius = value</pre></div><div id="d5a6"><pre><span class="hljs-keyword">def</span> <span class="hljs-title function_">area</span>(<span class="hljs-params"><span class="hljs-variable language_">self</span></span>):
    <span class="hljs-keyword">return</span> <span class="hljs-title class_">Circle</span>.<span class="hljs-variable constant_">PI</span> * <span class="hljs-variable language_">self</span>.radius * <span class="hljs-variable language_">self</span>.radius</pre></div><p id="1ecd">Because class attributes are created during class definition, while instance attributes will be assigned again when a new instance is created. It’s not only more convenient but also more efficient if we define some constants/default values as class attributes.</p><p id="f244">2. Record some data which is across all instances.</p><div id="574a"><pre><span class="hljs-keyword">class</span> HandsomeGuy(<span class="hljs-keyword">object</span>):
all_names = []

def __init__(self, <span class="hljs-keyword">name</span>):
    self.<span class="hljs-keyword">name</span> = <span class="hljs-keyword">name</span>
    Person.all_names.append(<span class="hljs-keyword">name</span>)</pre></div><h1 id="a540">Conclusion</h1><p id="d012">To be a Senior Python Developer, we should have a deeply understanding of some features and avoid unexpected bugs. The differences between class attributes and instance attributes are important but not everyone is totally clear with that. To summary, remember the two suggestions mentioned in this post:</p><ul><li><b>Do not use the same name for instance attributes and class attributes.</b></li><li><b>Always define class attributes as immutable objects to avoid unintended results.</b></li></ul><p id="5fb0"><b><i>Thanks for reading. If you like it, please follow my publication <a href="https://medium.com/techtofreedom">TechToFreedom</a>, where you can enjoy other Python tutorials and topics about programming, technology and investment.</i></b></p></article></body>

Class Attribute and Instance Attribute of Python

Photo by Gena Okami on Unsplash

Introduction

A Python object has two types of attributes: Class Attribute and Instance Attribute.

As the above example, class_attr is a class attribute and self.instance_attr is an instance attribute. Sometimes it’s really confusing. Why we have two types? Why not always define attributes as class attribute or instance attribute? What are differences of them? This post will uncover the mystery for you.

What’s the Differences

  • A class attribute is a variable which belongs to a class rather than a particular instance. All instances of this class can access it and it is defined outside the constructor function, __init__(self,...), of the class.
  • An instance attribute inside the constructor function is a variable belonging to a particular instance of a class. This variable is only accessible in this instance rather than the class. If we call a instance attribute by the class, there will be an AttributeError.

Why the Differences?

Because these two attributes are in different namespaces. The namespace means a dictionary which contains mappings of names and objects. It helps us call an object by its name conveniently. There is no relations between names in different namespaces. We can use print __dict__ to the namespace of an object.

As the above example shown, the namespace of the class doesn’t has instance_attr , so we can’t access it.

However, why can we access the class_attr by the instance even there is no class_attr in my_instance.__dict__ ? Because the rule of namespace is: searching the namespace of a instance first, if nothing found, searching its class namespace. It is a bottom up method rather than a top down method. Therefore, we can’t access the instance namespace by the class but we can access the class namespace by its instance.

There is an interesting problem: if the class attribute and instance attribute have the same name, what will happen?

Photo by Andre Mouton on Unsplash

Let’s look an example:

As shown above, namespace of instance has priority over namespace of class, so the guy.name is “Jack” at the beginning. After del guy.name , we don’t have name attribute in instance namespace, if we use the same name again, the class attributes will be accessed.

My suggestion is: when writing a program, do not use the same name for instance attributes and class attributes. It could result in unintended consequences because sometimes we could forget which type of attribute we are using if their names are the same.

By the way, Yang is really an handsome guy. If you don’t believe it, please look the example code again. 😄

Change Values of Class Attribute

The rules are:

  • If we change the value of a class attribute by the class, we will get the new value of course when we access it by instances.
  • However, if we change the value of a class attribute by an instance, the result is a little complicated, two different consequences for two situations:
  1. If this attribute is immutable, the attribute will become a instance attribute within current instance, the value changes will not affect other instances and the class.

2. If this class attribute is mutable, the results depend on how we change it.

My suggestion is: always define class attributes as immutable objects to avoid unintended results. For this example, we can define like this:

class MyClass(object):
    data = None

    def __init__(self, value):
        self.instance_data = value
Photo by Jen Theodore on Unsplash

We define the data as None rather than list.

It looks like just a minor issue. But, actually it will avoid lots of hidden bugs in a big project. If you are in an interview, how you define the data will show whether you are Senior Python Developer or not.

When to Use Class Attribute

  1. Define some constant or default value as class attribute which can use for every instances.
class Circle(object):
    PI = 3.14

    def __init__(self, value):
        self.radius = value
def area(self):
        return Circle.PI * self.radius * self.radius

Because class attributes are created during class definition, while instance attributes will be assigned again when a new instance is created. It’s not only more convenient but also more efficient if we define some constants/default values as class attributes.

2. Record some data which is across all instances.

class HandsomeGuy(object):
    all_names = []

    def __init__(self, name):
        self.name = name
        Person.all_names.append(name)

Conclusion

To be a Senior Python Developer, we should have a deeply understanding of some features and avoid unexpected bugs. The differences between class attributes and instance attributes are important but not everyone is totally clear with that. To summary, remember the two suggestions mentioned in this post:

  • Do not use the same name for instance attributes and class attributes.
  • Always define class attributes as immutable objects to avoid unintended results.

Thanks for reading. If you like it, please follow my publication TechToFreedom, where you can enjoy other Python tutorials and topics about programming, technology and investment.

Python
Object Oriented
Tutorial
Programming
Computer Science
Recommended from ReadMedium