What is the difference between classes initialized with (and without) __init___

Asked

Viewed 690 times

3

I’m a beginner in Python and I wanted to understand a difference. The two classes below produce exactly the same result and the variables become public in the same way in both classes:

class c():
    t = "abc"
    print (t)
    for a in range (3):
        print (a)

class d():
    def __init__(self):
        self.t = "abc"
        print (self.t)
        self.a = 0
        for self.a in range(0, 3):
            print(self.a)

c1 = c()
d1 = d()

Upshot:

abc
0
1
2
abc
0
1
2

Why then should I use the builder __init__ if at the end of the day the results are the same?

  • That? https://answall.com/q/109013/101

  • @Maniero, I read these articles, but I still don’t understand why to use __init__ if in my example the results are the same?

1 answer

9


They are not the same. In your example it was almost mere coincidence. Just do not instantiate the class c who will see what happens.

This is because classes are only a scope limiter in Python. You can enter codes normally within the class, not only definitions of fields and methods, but also occur in other languages. The difference is that this code will execute when the class is defined.

class c():
    t = "abc"
    print (t)
    for a in range (3):
        print (a)

This will already show in the terminal even if the class is not instantiated, different from the class d, that implements the initializer method, which will have the logic executed only when instantiated.

You can use this to define compatibility with different versions of Python. Let’s say that a method has functionalities that vary according to the version to be executed and you intend to maintain support for both, could do something like:

import sys

class Foo:

  if sys.version_info[0] == 3:
    def something(self):
     return 'Python 3'
  else:
    def something(self):
      return 'Python 2'

foo = Foo()

print(foo.something())

See working on Python 3 and in the Python 2

Obviously we would not do something of this kind for such a simple method, but when you start working with some more differences drastic between versions, such as using the method __str__ or __unicode__, this approach starts to make sense.

Not to mention the difference that when you define a field without associating to self, you will be defining a class attribute, while when used next to the self will be an instance attribute. This will make all the difference when the type worked is changeable, because being mutable and being class attribute, once modified the modification will be reflected in all instances.

class Foo:
    field = []

a = Foo()
a.field.append(1)

print(a.field)  # [1]

b = Foo()

print(b.field)  # [1]

See working on Repl.it

Already, if used within __init__, with the self, the exit of b.field would be [], would be an independent list of a.field, even if they are instances of the same class. In your case, c.t will be a class attribute while d.t will be an instance attribute.

  • thank you. In short, I understood that basically in my example, the class "c" is executed independently of being instantiated and the class "d" will be executed only when instantiated. But in practice, the results are the same. But, apart from the issue of compatibility of Python versions, remaining only in version 3, there would be some more real difference, except for the moment when classes are initialized?

  • @Rogériodec this question of scope (class attribute or instance) that I added at the end of the answer

  • Now I get it! Class attribute x instance attribute. Thank you so much for the explanation!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.