Possible Duplicate:
Variables inside and outside of a class __init__() function
I understand that when a class is called it will run the code in __init__
before anything. I still don't see the difference between that, and writing the code directly under the class.
For example:
class main():
x = 1
def disp(self):
print self.x
class main():
def __init__(self):
self.x = 1
def disp(self):
print self.x
To me, both have the same functionality. (Maybe I am missing out something.) I would like to know which is more (ahem) pythonic and why.
There are a couple key differences here, both between __init__
and writing it just under the class, as well as what you wrote.
Working with x = 1
First, you are right--these two items of code do effectively the same thing for your purposes (specifically because we're working with int
objects here, this would be different for mutable objects):
Note that they don't actually do the same thing--please see the comments on this answer for clarification.
class main(object):
x = 1
class main(object):
def __init__(self):
self.x = 1
This is why many non-standard Python libraries, like mongoengine
and django
models, have a standard where you create classes without using an __init__
statement so as not to override the built-in one, but still allowing you to create class attributes, e.g., a Django example:
class mymodel(models.model):
name = models.CharField(max_length=20)
url = models.UrlField()
However, as the other poster points out, there is a difference between the two in that when x=1
is outside of the __init__
function, it is part of the class itself even when not intialized--see Zagorulkin Dmitry's answer for more detail on that. In most cases, though, that distinction won't be relevant for you.
Other considerations
There are more uses for __init__
beyond just setting variables. The most important one offhand is the ability to accept arguments during initialization. To my knowledge, there is not a way to do this without an __init__
function. I'll show you what I mean by this in this example.
Let's say we're creating a Person
class, and when we create a Person
, we supply their age, and then their birth year is automatically calculated from that for us.
import datetime
class Person(object):
def __init__(self, age):
self.age = age
self.birth_year = (datetime.date.today() - datetime.timedelta(days=age*365)).year
In use:
>>>joe = Person(23)
>>>joe.age
23
>>>joe.birth_year
1990
This wouldn't be possible without __init__
, since we couldn't pass the initialization the age
argument otherwise.
Yes, as stated in various other questions, variables defined within the class body are attributes of the class, whereas those defined in a def __init__(self)
block are attributes of an instance of a class.
Difference between defining a member in init to defining it in the class body in Python?
As already indicated, class attributes (assigned at class level) and instance attributes (assigned as a self attribute for example in __init__
) are different.
On the other hand, in your first class you are defining two different attributes (class x
and instance x
) that coexist, but that can interfere with each other. The code below try to show the problems you can get if you define the class that way.
In [32]: class main():
....: x = 1
....: def disp(self):
....: print(self.x)
....:
# I create 2 instances
In [33]: jim = main()
In [34]: jane = main()
# as expected...:
In [35]: main.x
Out[35]: 1
In [36]: jim.x
Out[36]: 1
In [37]: jane.x
Out[37]: 1
# now, I assign to jim attribute x
In [38]: jim.x = 5
# main class preserves its attribute value as well as jane instance
In [39]: main.x
Out[39]: 1
In [40]: jane.x
Out[40]: 1
# But what happens if I change the class attribute ?
In [41]: main.x = 10
# nothing to jim (I overwrote before jim.x)
In [42]: jim.x
Out[42]: 5
# but jane did see the change
In [43]: jane.x
Out[43]: 10
Let us consider the following class definition:
class Main:
x = 1
def __init__(self):
self.y = 5
In this case, we can refer x directly like: Main.x
i.e. it is a class attribute, this belongs to every objects of this class.
>>>Main.x
1
But, attribute y
is specific to each object. We can not refer it directly like this:
>>> Main.y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: class Main has no attribute 'y'
You need to instantiate an object of the class Main to refer to y:
>>> obj = Main()
>>> obj.y
5
This is similar to static
variables in C++ and Java.
it's different.
in first example you have x
without initialization.
>>> class main():
... def __init__(self):
... self.x =1
...
>>> test2 = main()
>>> dir(test2)
['__doc__', '__init__', '__module__', 'x']
>>> class main1():
... x =1
... def disp(self):
... print self.x
...
>>> dir(main1)
['__doc__', '__module__', 'disp', 'x']
>>> dir(main)
['__doc__', '__init__', '__module__']
>>>