If an instance variable is not set in __init__() can it be referenced by a class method?

Question

If an instance variable is not initialized in the __init__() function, can it still be referenced by a class method?

Answer

Yes, the instance variable can be referenced by a class method using self so long as it has been set before the call. If not, an AttributeError will be generated. As a general rule, it is best to initialize all of the instance variables in the __init__() function for consistency.

10 Likes

__init__() is what defines instance variables. Any other is a class variable until an instance changes it within its own context, thereby adopting a new instance variable.

22 Likes

They pyDocs have a good example of the difference between class and instance variables

“”"
instance variables are for data unique to each instance and class variables are for attributes and methods shared by all instances of the class:
“”"

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind                  # shared by all dogs
'canine'
>>> e.kind                  # shared by all dogs
'canine'
>>> d.name                  # unique to d
'Fido'
>>> e.name                  # unique to e
'Buddy'
68 Likes

So, ‘store_name’ listed in scenario #1 is the same as calling a variable inside the init method of scenario #2? If so, are there any specific cases where we might use instance variables like the one listed in scenario #1?

alternative_rocks = Store(). # Store is the class name
alternative_rocks.store_name = “Alternative Rocks”

class Store:
def init(self, store_name):
self.store_name = store_name

We use the __init__() method so we can instantiate values particular to that instance. The variables once created are free of that method, which only runs once, ever.

An object has been created that has unique attributes. It won’t mean that other objects cannot have those values, but it does mean that now we can actually group objects by their coincidence on certain attribute values. A cool way to look at data.

1 Like

Thanks @mtf. I earlier didn’t understand the importance of ‘init’ runs once during instantiation but now I understand.

When you said “actually group objects by their coincidence on certain attribute values”, are you referring to comparing the values of instance variables of 2 different objects for the same class?

Let me know if my understanding is incorrect. Slowly trying to make my way through classes and understand it.

1 Like

Precisely. Two instances of the same class will have common attributes, though their values will be distinct to each instance. We can then compare attribute values.

We won’t need to group them, though. They already are a group, and they have a name… The attribute.

1 Like

Got it. Thanks for clarifying.

1 Like

You’re welcome. Here is something further to consider…

We have two circles. One has a radius of p and the other of q. Given that q is double what p is. by the Law of Squares we know that the area of the circle with radius q will be four times the area of the circle with radius p.

In a classified date structure with such computing ability we can readily compare any number of like objects. In geometry we call this, similarity.

How many triangles can you draw when the angles never change? How many triangles can you draw where the side lengths never change?

Answer: Infinite, and, three. Similarity sides with the first result.

2 Likes

Oh, if you count transformations,

infinite

and,

12

.____

It is not about math, as some would hold. We all have it within us to see the numbers and how they relate. Some math might be needed to analyze what we see, but it doesn’t have to be us doing the math to see it.

If we want to understand what the math is telling us, then math it is. But, it should not keep us from seeing what it is we just saw.

It’s why I love Cosmology.

1 Like

Fantastic differentiation, thank you so much for posting this!

This might have been asked already, but I still don’t understand the difference between defining instance variables using __init__ vs directly using the object.

This

class Store:
    def __init__(self,store_name):
        self.store_name = store_name

alternative_rocks = Store("Alternative Rocks")
alternative_rocks.store_name

vs this

class Store():
    pass

alternative_rocks = Store()
alternative_rocks.store_name = "Alternative Rocks"
alternative_rocks.store_name
4 Likes

From a programming perspective it may prove more beneficial to have attributes defined in the class so that every instance has them in common and our program does not run the risk of raising an AttributeError because an instance does not have an expected attribute.

6 Likes

Got it, that makes sense, thank you!

1 Like

Is it considered a better practice to define and assign values to instance variables via the constructor as in:

class Foo:
    def __init__(self, val):
         self.instace_variable = val

or, “on the fly” as is shown in the lesson with the class FakeDict and the instance variable fake_key?
My guess is the first option since it imposes structure and avoid spelling errors…

1 Like

Yes the first option is normally a much better choice. On the fly makes it hard to keep track of what attributes any one instance has whereas the constructor makes it abundantly clear. Where possible stick with the first and if not try adding new attributes with method calls and such to keep it as clear as possible how each instance behaves.

3 Likes

This is what you are referring to, yes?

class Store:
  store_name = "PlaceHolder"


alternative_rocks = Store()
alternative_rocks.store_name = "Alternative Rocks"

isabelles_ices = Store()
isabelles_ices.storename = "Isabelle's Ices"


print(alternative_rocks.store_name)
# prints Alternative Rocks

print(isabelles_ices.store_name)
# prints PlaceHolder

print(isabelles_ices.storename)
# prints Isabelle's Ices

It’s better to “definitively establish” a class variable when said variable will likely exist across all instances to avoid discrepancies in variable naming.

1 Like

Once an instance supplies a new value, the variable becomes an instance variable and the class variable is shadowed.

print(Store.store_name)
print(isabelles_ices.store_name)
PlaceHolder
PlaceHolder

By the same token instances cannot declare new class variables.

print (Store.storename)
Traceback (most recent call last):
    print (Store.storename)
AttributeError: type object 'Store' has no attribute 'storename'

So, my next question: once a Class is instantiated as an object are the variables only considered instance variables? Or, only if the Class variable is over-written?

Those that are declared in the constructor (__init__()) are the instance variables that are unique to that instance. Class variables are accessible to all instances and are usually limited to some value that all need in common.

1 Like