explicit call to __init__(self) in subclass needed?

A

Andrew MacKeith

I create a class like this in Python-2.6
.... def __init__(self, s):
.... pass
....
How does the base class (str) get initialized with the value passed to Y.__init__() ?

Is this behavior specific to the str type, or do base classes not need to be explicitly initialized?

Andrew
 
E

Ethan Furman

Andrew said:
I create a class like this in Python-2.6

... def __init__(self, s):
... pass
...

How does the base class (str) get initialized with the value passed to
Y.__init__() ?

Is this behavior specific to the str type, or do base classes not need
to be explicitly initialized?

Andrew

All the immutable base types (I *think*), use __new__ for object
creation, not __init__.

~Ethan~
 
B

Bruno Desthuilliers

Ethan Furman a écrit :
All the immutable base types (I *think*), use __new__ for object
creation, not __init__.

All types use __new__ for object *creation*. __init__ is for object
initialization (which indeed happens in the __new__ method for immutable
types, since the initializer works my mutating the newly created
instance) !-)
 
B

Bruno Desthuilliers

Andrew MacKeith a écrit :
I create a class like this in Python-2.6

... def __init__(self, s):
... pass
...

How does the base class (str) get initialized with the value passed to
Y.__init__() ?

It happens in the __new__ method (which is the proper "constructor")

class Y(str):
def __new__(cls, value, foo="foo"):
instance = str.__new__(cls, value)
instance.foo = foo
return instance

def __repr__(self):
Is this behavior specific to the str type, or do base classes not need
to be explicitly initialized?

When you override a method in a derived class, it's your responsability
to call on the parent(s) class(es) implementation. __init__ is not an
exception to that rule. The point is that since __init__ works by
mutating the newly created instance, it makes no sense to have a
distinct __init__ for immutable types - which have their "value" set
once for all at creation time.
 
E

Ethan Furman

Bruno said:
Ethan Furman a écrit :



All types use __new__ for object *creation*. __init__ is for object
initialization (which indeed happens in the __new__ method for immutable
types, since the initializer works my mutating the newly created
instance) !-)

Thanks for the clarification, Bruno!

~Ethan~
 
A

Andrew MacKeith

Bruno said:
Andrew MacKeith a écrit :

It happens in the __new__ method (which is the proper "constructor")

class Y(str):
def __new__(cls, value, foo="foo"):
instance = str.__new__(cls, value)
instance.foo = foo
return instance

def __repr__(self):


When you override a method in a derived class, it's your responsability
to call on the parent(s) class(es) implementation. __init__ is not an
exception to that rule. The point is that since __init__ works by
mutating the newly created instance, it makes no sense to have a
distinct __init__ for immutable types - which have their "value" set
once for all at creation time.

Thanks for the explanation, Bruno.

I have been successfully using a class derived from str, and in that
class I add a lot of extra data to the derived class instance in the
__init__ method of the derived class, so it is possible to mutate the
derived class __dict__, even if the base class data remains immutable.


See example below.

The __init__ must have the same arguments as the base class.
.... def __init__(self):
.... self.color = 'blue'
....Traceback (most recent call last):
.... def __init__(self, text):
.... self.color = 'blue'
....
>>> y = Y('Parrot')
>>> y 'Parrot'
>>> y.color 'blue'
>>> y[:3] 'Par'
>>> y.size = 'small'
>>>
>>> y.__class__

But you can get bitten if you do something that returns a new object
Traceback (most recent call last):

Andrew
 
B

Bruno Desthuilliers

Andrew MacKeith a écrit :
Thanks for the explanation, Bruno.

I have been successfully using a class derived from str, and in that
class I add a lot of extra data to the derived class instance in the
__init__ method of the derived class, so it is possible to mutate the
derived class __dict__, even if the base class data remains immutable.

Indeed. What I said was that Python builtins immutable types didn't use
the initializer, not that you couldn't use an initializer in derived
classes. I gave an example using __new__ because, quite often when
subclassing immutable types, peoples want to access the initial value
_before_ the call to the base class.
See example below.

The __init__ must have the same arguments as the base class.

The initializer (__init__) must have the same arguments as the
constructor (__new__). This is true for all and every classes.

(snip)
But you can get bitten if you do something that returns a new object

Traceback (most recent call last):

You need to override a couple other __magic_methods__ to make this work.
You'll find relevant documentation here:

http://docs.python.org/reference/datamodel.html#special-method-names

In the above case, you want to override at least the __add__ method:

class Y(str):
def __new__(cls, value, foo="foo"):
instance = str.__new__(cls, value)
instance.foo = foo
return instance

def __repr__(self):
return "<%s(%s, %s)>" % (type(self).__name__, self, self.foo)

def __add__(self, other):
return type(self)(str(self) + other, self.foo)

HTH
 

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,776
Messages
2,569,603
Members
45,200
Latest member
LaraHunley

Latest Threads

Top