Erik said:
I'm new to Python, and OOP. I've read most of Mark Lutz's book and more
online and can write simple modules, but I still don't get when __init__
needs to be used as opposed to creating a class instance by assignment.
nothing is ever created by plain assignment in Python; to create a class
instance in Python, you *call* the class object. an example:
class MyClass:
pass
# create three separate instances
obj1 = MyClass()
obj2 = MyClass()
obj3 = MyClass()
(it's the () that creates the object, not the =)
if you want to initialize the method's state (that is, set some
attributes), you can do that from the outside:
obj1.attrib = "some value"
or in an "initialization" method in the class:
class MyClass:
def init(self):
self.attrib = "some value"
obj1 = MyClass()
obj1.init()
but in both cases, you'll end up with an inconsistent object state (in
this case, no attribute named "attrib") if you forget to do this.
obj1 = MyClass()
print obj1.attrib # this will fail
to avoid such mistakes, you can use __init__ instead. this is just a
initialization method that's automatically called by Python *after* the
object is created, but *before* the call to the class object returns.
class MyClass:
def __init__(self):
self.attrib = "some value"
obj1 = MyClass()
print obj1.attrib # this will succeed
also, any arguments that you pass to the class object call are passed on
to the initialization method.
class MyClass:
def __init__(self, value):
self.attrib = value
obj1 = MyClass("hello")
print obj1.attrib # prints "hello"
as Jeroen points out, this is pretty much the same thing as a
constructor in other languages -- that is, a piece of code that's
responsible for setting up an object's state.
Python's a bit different; the object is in fact created before the
call to __init__, but this doesn't matter much in practice; if
construction fails, the assignment will fail, so the object will be
lost, and is reclaimed by the GC later on.
(unless you explicitly store a reference to the object somewhere else,
of course:
.... def __init__(self):
.... global secret
.... secret = self
.... raise ValueError("oops! failed!")
.... def method(self):
.... print "here I am!"
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Traceback (most recent call last):
here I am!
)
finally, if you want full control also over the actual creation of the
object, more recent Python versions support a __new__ method that can be
used instead of __init__, or as a complement. but that's an advanced
topic, and is nothing you need to worry about while trying to the hang
of class basics.
hope this helps!
</F>