16

I'm new to Python - and just trying to better understand the logic behind certain things.

Why would I write this way (default variables are in __init__):

class Dawg:


    def __init__(self):
        self.previousWord = ""
        self.root = DawgNode()
        self.uncheckedNodes = []
        self.minimizedNodes = {}

    def insert( self, word ):
        #...

    def finish( self ):
        #...

Instead of this:

class Dawg:
    previousWord = ""
    root = DawgNode()
    uncheckedNodes = []
    minimizedNodes = {}

    def insert( self, word ):
        #...

    def finish( self ):
        #...

I mean - why do I need to use __init__ -> if I can just as easily add default variables to a class directly?

Dannyboy
  • 1,963
  • 3
  • 20
  • 37
  • There's no such thing as a "default variable". Class variables and instance variables are two very distinct concepts, each of which may have a default *value*. – chepner Jul 14 '14 at 15:19
  • I think this is fine question, but it already has answer here: [Static class variables in Python](http://stackoverflow.com/questions/68645/static-class-variables-in-python) – Vyktor Jul 14 '14 at 15:19
  • 8
    Excellent question. Your wording makes your question (and its answers) very easy to find for searchers relatively new to Python. – David Pointer Jul 14 '14 at 16:15

2 Answers2

27

When you create variables in the Class, then they are Class variables (They are common to all the objects of the class), when you initialize the variables in __init__ with self.variable_name = value then they are created per instance and called instance variables.

For example,

class TestClass(object):
    variable = 1

var_1, var_2 = TestClass(), TestClass()
print var_1.variable is var_2.variable
# True
print TestClass.variable is var_1.variable
# True

Since variable is a class variable, the is operator evaluates to True. But, in case of instance variables,

class TestClass(object):
    def __init__(self, value):
        self.variable = value

var_1, var_2 = TestClass(1), TestClass(2)
print var_1.variable is var_2.variable
# False
print TestClass.variable is var_1.variable
# AttributeError: type object 'TestClass' has no attribute 'variable'

And you cannot access an instance variable, with just the class name.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • Could you add an explanation of why one would want to use instance variables versus class variables and vice versa for those who don't know the difference? – RevanProdigalKnight Jul 14 '14 at 15:18
  • So, for C++ programmers, those defined in the class are implicitly static member variables and those defined inside `__init__` are normal member variables. @RevanProdigalKnight For a Book class, you would define things like bookname as instance variables and `__version__`, for versioning your Book class itself, as a class variable. – mxmlnkn Dec 13 '20 at 00:47
4

When you write this:

class Dawg:
    previousWord = ""
    root = DawgNode()
    uncheckedNodes = []
    minimizedNodes = {}

Those are not instance variables, they're class variables (meaning: the same variables with the same values are shared between all instances of the class.) On the other hand, this:

class Dawg:
    def __init__(self):
        self.previousWord = ""
        self.root = DawgNode()
        self.uncheckedNodes = []
        self.minimizedNodes = {}

... Is declaring instance variables, meaning: the values are different for each instance of the class. As you see, each snippet means a completely different thing, and you have to pick the one that is appropriate for you. Hint: most of the time you're interested in instance variables, because class variables define a kind of shared global state for your objects, which is error prone.

Óscar López
  • 232,561
  • 37
  • 312
  • 386
  • interesting. So if I have 2 objects of class Dawg - and I set previousWord = 'test' on one of them -> it will become 'test' in a second object too? This seem to be different from other languages like PHP for example... – Dannyboy Jul 14 '14 at 15:20
  • 1
    @Dannyboy yes, both objects will see the change if they're declared as _class_ variables. It's the same thing in PHP, Java, etc. when you use class attributes. That's why they must be used with care, and most of the time you want instance variables anyway. – Óscar López Jul 14 '14 at 15:25
  • 4
    @Dannyboy No, `obj1.previousWord = "test"` will just create an instance attribute and not affect that `obj2` doesn't have such an instance attribute and still sees the class variable's value (`""`). However, `obj1.uncheckedNodes.append(something)` will modify the shared list (i.e. it'll affect `obj2.uncheckedNodes`). This is the difference between attribute assignment and method calls. –  Jul 14 '14 at 15:26
  • @ÓscarLópez it's not the same in PHP, Java. In PHP when I call `$obj = new Object();` -> all variables that are defined in class-block will be unique to each separate $obj instance. So it seems like in Python it's different - these variables are like global shared class-level registry. – Dannyboy Jul 14 '14 at 15:31
  • @Dannyboy yes, it's the same _concept_. Don't get confused with Python's syntax. Both Python and Java have static and instance variables. In Java you identify class variables because they're declared at the class level as `static`, whereas in Python they're declared inside the class. Similarly, in Java instance variables are those declared at the class level _without_ `static`, whereas in Python you declare them inside `__init__` – Óscar López Jul 14 '14 at 15:35
  • @Dannyboy in fact, is incorrect to say that in Java "all variables that are defined in class-block will be unique to each separate instance". Those that were declared as `static` will be shared among all instances. – Óscar López Jul 14 '14 at 15:37