__init__ explanation please

E

Erik Lind

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. For
some strange reason the literature seems to take this for granted. I'd
appreciate any pointers or links that can help clarify this.

Thanks
 
D

Daniel Fetchinson

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. For
some strange reason the literature seems to take this for granted. I'd
appreciate any pointers or links that can help clarify this.

I'm not sure if I understand your question correctly but maybe this will help:

If you want code to be run upon creating an instance of your class you
would use __init__. Most common examples include setting attributes on
the instance and doing some checks, e.g.

class Person:
def __init__( self, first, last ):
if len( first ) > 50 or len( last ) > 50:
raise Exception( 'The names are too long.' )
self.first = first
self.last = last

And you would use your class like so,

p1 = Person( 'John', 'Smith' )
p2 = Person( "Some long fake name that you don't really want to
except, I don't know if it's really longer than 50 but let's assume it
is", "Smith" )
# This last one would raise an exception so you know that something is not okay

HTH,
Daniel
 
C

Colin J. Williams

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. For
some strange reason the literature seems to take this for granted. I'd
appreciate any pointers or links that can help clarify this.

Thanks
You don't always need __init__ if
__new__ is used with a "new" class.

Colin W.
 
D

Daniel Fetchinson

Please keep discussion on the list......
Is not the code run when I create an instance by assignement somewhere else?

I take the point that one might want to check for potential exceptions
immediately, but most examples in the literature aren't doing that and don't
seem to be doing anything that would not be done when creating an instance
by assignment later somewhere. I'm missing something basic here.

What do you mean by "create an instance by asignment somewhere else"?
 
J

Jeroen Ruigrok van der Werven

-On [20080113 01:41] 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.

I personally tend to see __init__ or __new__ as equivalent to what other
languages call a constructor.

(And I am sure some people might disagree with that. ;))

--
Jeroen Ruigrok van der Werven <asmodai(-at-)in-nomine.org> / asmodai
イェルーン ラウフロック ヴァン デル ウェルヴェン
http://www.in-nomine.org/ | http://www.rangaku.org/
The riddle master himself lost the key to his own riddles one day, and
found it again at the bottom of his heart.
 
F

Fredrik Lundh

Jeroen said:
I personally tend to see __init__ or __new__ as equivalent to what other
languages call a constructor.

(And I am sure some people might disagree with that. ;))

given that they do different things, I'm not sure it's that helpful to
describe them *both* as constructors.

</F>
 
F

Fredrik Lundh

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>
 
B

Ben Finney

Jeroen Ruigrok van der Werven said:
-On [20080113 01:41] 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.

I personally tend to see __init__ or __new__ as equivalent to what
other languages call a constructor.

That's getting the two of them confused. __new__ is a constructor,
__init__ is not.
(And I am sure some people might disagree with that. ;))

It isn't really a matter for much debate.

<URL:http://www.python.org/doc/ref/customization.html>

__new__ is the constructor: it creates the instance and returns it.

Along the way, it calls __init__ on the *already-created* instance, to
ask it to initialise itself ready for use. So, __init__ is an
"initialiser" for the instance.

Python, unlike many other OO languages, fortunately has these two
areas of functionality separate. It's far more common to need to
customise instance initialisation than to customise creation of the
instance. I override __init__ for just about every class I write; I
can count the number of times I've needed to override __new__ on the
fingers of one foot.
 
A

A.T.Hofkamp

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. For
some strange reason the literature seems to take this for granted. I'd
appreciate any pointers or links that can help clarify this.

I think you mean the following:
You'd like to do

p = Person('me', 'here', 31)

and you are wondering why you need the __init__() function in

class Person(object):
def __init__(self, name, addres, age):
self.name = name
self.address = address
self.age = age

right?

If so, the answer is that while you think you are doing "Person('me', 'here', 31)",
you are in reality executing "Person.__init__(self, 'me', 'here', 31)", where
'self' is refers to a shiny new, empty object created for you.

(and the 'self' is obtained by the Person.__new__ function I think, but others
here have much better knowledge about this).


Sincerely,
Albert
 
B

Ben Finney

A.T.Hofkamp said:
while you think you are doing "Person('me', 'here', 31)", you are in
reality executing "Person.__init__(self, 'me', 'here', 31)", where
'self' is refers to a shiny new, empty object created for you.

This is misleading, and founders on many discrepancies, not least of
which is that '__init__' always returns None, yet the 'Person()' call
returns the new instance. So it's quite untrue to say that one is "in
reality" calling the '__init__' method.

What one is "in reality" calling is the '__new__' method of the Person
class. That function, in turn, is creating a new Person instance, and
calling the '__init__' method of the newly-created instance. Finally,
the '__new__' method returns that instance back to the caller.
 
J

Jeroen Ruigrok van der Werven

-On [20080113 13:36] said:
given that they do different things, I'm not sure it's that helpful to
describe them *both* as constructors.

I am still behind in my learning. ;)

To restate it more correctly: __init__ is akin to a constructor.

I am not entirely sure I fully understand __new__'s semantics though. The
first read-through of http://docs.python.org/ref/customization.html makes it
sound very similar to a call like: var = Object(arguments=...)

I must not be understanding something and __new__'s documentation there is not
that clear to me, to be honest.
 
J

Jeroen Ruigrok van der Werven

-On [20080113 14:03] said:
That's getting the two of them confused. __new__ is a constructor,
__init__ is not.

And there I just sent an email stating the wrong thing.

I'll dig into it again, because I am really confusing something here (and
jumping between 4 languages on the same day is not helping much to be honest).
 
H

Hrvoje Niksic

Ben Finney said:
What one is "in reality" calling is the '__new__' method of the Person
class. That function, in turn, is creating a new Person instance, and
calling the '__init__' method of the newly-created instance. Finally,
the '__new__' method returns that instance back to the caller.

This is also not entirely correct. __new__ doesn't call __init__; if
it did, there would be no way to call __new__ without also calling
__init__ (pickle, among other things, does that and needs to do that
to correctly implement its logic).

"In reality" executing Person(...) invokes the __call__ method of
type(Person) (normally the standard metatype called "type") bound to
the Person type object. This is where the logic to call __new__
followed by __init__ is implemented, in code that does something close
to this:

obj = mytype.__new__(*args, **kwds)
if isinstance(obj, mytype):
mytype.__init__(obj, *args, **kwds)
return obj
 
W

Wildemar Wildenburger

Jeroen said:
To restate it more correctly: __init__ is akin to a constructor.
No. See Hrvoje Niksic's reply (and Ben Finney's to which it was a reply).

__init__() /initializes/ an instance (automatically after creation). It
is called, /after/ the instance has been constructed via the __new__()
method.
__new__() actually /constructs/ a new instance.

I am not entirely sure I fully understand __new__'s semantics though.
Create a new (blank) instance of a class and return it. That's all there
is to it.

I must not be understanding something and __new__'s documentation there is not
that clear to me, to be honest.
It is somewhat confusing at first. But just bear in mind: 99 out of 100
times, you don't need to override __new__(). When you need it, you'll know.

/W
 
H

Hrvoje Niksic

Wildemar Wildenburger said:
No. See Hrvoje Niksic's reply (and Ben Finney's to which it was a
reply).

__init__() /initializes/ an instance (automatically after
creation). It is called, /after/ the instance has been constructed

I don't understand the purpose of this "correction". After all,
__init__ *is* the closest equivalent to what other languages would
call a constructor. Take C++ and Java, the two most popular OO
languages in existence. Their constructors also "initialize" an
instance -- the actual allocation is left to the caller (new or stack
in C++) or to the garbage collector. They even share with Python the
convention of not returning the constructed value, they operate purely
on side effect, just like Python's __init__. And yet, no one says
that they are somehow not constructors because of that.

Wikipedia calls the constructor "a special method used in object
oriented programming which puts the object's members into a valid
state." Again, exactly what __init__ does.
 
M

Mel

Hrvoje said:
I don't understand the purpose of this "correction". After all,
__init__ *is* the closest equivalent to what other languages would
call a constructor.

Nevertheless, __init__ doesn't construct anything. You can even call
it to reinitialize an existing object:


Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information..... def __init__ (self):
.... self.a = 4
....4



Cheers, Mel.
 
H

Hrvoje Niksic

Mel said:
Nevertheless, __init__ doesn't construct anything.

Only if by "construct" you mean "allocate". __init__ starts out with
an empty object and brings it to a valid state, therefore
"constructing" the object you end up with. That operation is exactly
what other languages call a constructor.
 
R

Reedick, Andrew

-----Original Message-----
From: [email protected] [mailto:python-
[email protected]] On Behalf Of Hrvoje Niksic
Sent: Monday, January 14, 2008 11:29 AM
To: (e-mail address removed)
Subject: Re: __init__ explanation please

Mel said:
Nevertheless, __init__ doesn't construct anything.

Only if by "construct" you mean "allocate". __init__ starts out with
an empty object and brings it to a valid state, therefore
"constructing" the object you end up with. That operation is exactly
what other languages call a constructor.


Nah. Most other languages combine the constructor and an init function.
Normally with c++ I'll have the constructor call an Init() function so I
can re-initialize the object as needed. Python has explicitly split the
two.


Besides, the Python docs say that __new__ is the constructor and
__init__ may or may not be called after the instance is created:

__new__( cls[, ...])

Called to create a new instance of class cls. __new__() is a
static method (special-cased so you need not declare it as such) that
takes the class of which an instance was requested as its first
argument. The remaining arguments are those passed to the object
constructor expression (the call to the class). The return value of
__new__() should be the new object instance (usually an instance of
cls).

...
If __new__() returns an instance of cls, then the new instance's
__init__() method will be invoked
...
If __new__() does not return an instance of cls, then the new
instance's __init__() method will not be invoked.


__init__( self[, ...])

Called when the instance is created.
...
As a special constraint on constructors, no value may be
returned;



Also, how can a constructor require 'self' as an argument...?
__init__(self, ...)


If the __init__ function is called by the constructor it cannot return a
value. However if called as a normal function, it can return a value.
__init__ is just a function that gets called by the constructor, which
is __new__.


count = 0
class AClass (object):
def __init__ (self):
self.a = 4

global count
if count > 0:
return 'hello world'

count += 1


a = AClass()

print a.a
print a.__init__()


c:\foo\a.py>
4
hello world



*****

The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential, proprietary, and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers. GA622
 
N

Neil Cerutti

-----Original Message-----
From: [email protected] [mailto:python-
[email protected]] On Behalf Of Hrvoje Niksic
Sent: Monday, January 14, 2008 11:29 AM
Only if by "construct" you mean "allocate". __init__ starts out with
an empty object and brings it to a valid state, therefore
"constructing" the object you end up with. That operation is exactly
what other languages call a constructor.

Nah. Most other languages combine the constructor and an init function.
Normally with c++ I'll have the constructor call an Init() function so I
can re-initialize the object as needed. Python has explicitly split the
two.
Besides, the Python docs say that __new__ is the constructor and
__init__ may or may not be called after the instance is created:

The documentation of __new__ carefully refrains from calling __new__ a
constructor. Both __new__ and __init__ mention the object constructor
expression, e.g., "list()".
__init__( self[, ...])
Called when the instance is created.
...
As a special constraint on constructors, no value may be
returned;

Once again, the documentation is referring to constructor expressions.
As you noted, __init__ may return a value when not called by a
constructor expression.

C++'s constructor initialization lists are the closest thing to
Python's __new__. They can perform tasks for which Python might need
__new__. For example, a class member that's a reference must be
initialized in the initialization list, because it cannot be set once
the body of the constructor begins.
 
H

Hrvoje Niksic

Reedick said:
Nah. Most other languages combine the constructor and an init
function.

Maybe so, but the standard term for what Python calls __init__ is
still "constructor".
Also, how can a constructor require 'self' as an argument...?
__init__(self, ...)

Think of it as the equivalent of Java's and C++'s "this", except it's
explicit in the argument list. "Explicit is better than implicit" and
all that. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top