[Python-Dev] py3k: TypeError: object.__init__() takes no parameters

Terry Reedy tjreedy at udel.edu
Fri Jan 16 17:12:49 CET 2009


Nick Craig-Wood wrote:
> I've noticed with latest python 3.1 checkout (68631) if I have this
> object hierarchy with a default __init__ in the superclass to be used
> by the subclasses which don't necessarily need an __init__ it blows up
> with a TypeError.
> 
> class Field(object):

object is default baseclass, hence not needed

>     def __init__(self, data):
>         """Default init for the subclasses"""
>         print("init class=%r, self=%r" % (self.__class__.__name__, self))
>         super(Field, self).__init__(data)

This line is the problem: remove it and I believe all is fine.
Since object()s are immutable, its init cannot do anything as far as I 
know.  Deleting this is effectively what you did below.

Actually, I am puzzled why object even has __init__.  Perhaps to avoid 
hasattr(ob,'__init__') check  Doc implies that is it possible for a 
class to not have one.
"
object.__init__(self[, ...])
Called when the instance is created. The arguments are those passed to 
the class constructor expression. If a base class has an __init__() 
method, the derived class’s __init__() method, if any, must explicitly 
call it to ensure proper initialization of the base class part of the 
instance; for example: BaseClass.__init__(self, [args...]). As a special 
constraint on constructors, no value may be returned; doing so will 
cause a TypeError to be raised at runtime.
"
But in 3.0, *all* classes will inherit object.__init__.

 From super() doc...
"There are two typical use cases for “super”. In a class hierarchy with 
single inheritance, “super” can be used to refer to parent classes 
without naming them explicitly, thus making the code more maintainable."

I wonder about this claim.  This use of super() does not eliminate the 
need to pass legal args, so you have to know what actually is called, so 
why not name it?

>         self.data = self.orig = data
> 
> class IntegerField(Field):
>     def __init__(self, data):
>         """Overridden init"""

?? This over-rides and is not over-ridden.

>         super(IntegerField, self).__init__(data)
>         self.data = int(data)
> 
> class StringField(Field):
>     pass
> 
> f1 = StringField('abc')
> f2 = IntegerField('10')
> print("f1=%r" % f1.data)
> print("f2=%r" % f2.data)
> print(type(f1))
> print(type(f2))
> 
> It blows up with
> 
> init class='StringField', self=<__main__.StringField object at 0xb7d47b4c>
> Traceback (most recent call last):
>   File "subclass-super-problem-py3k.py", line 17, in <module>
>     f1 = StringField('abc')
>   File "subclass-super-problem-py3k.py", line 5, in __init__
>     super(Field, self).__init__(data)
> TypeError: object.__init__() takes no parameters
> 
> The exact same code runs under py 2.5 just fine.

Perhaps 2.5's object.__init__ just swallowed all args, thus hiding bogus 
calls.

> I can't think of anything to write in Field.__init__ to tell whether
> super is about to run __init__ on object.

I do not understand.  You know it is going to run the .__init__ of its 
one and only base class, which here is object.

> The problem can be fixed (inelegantly IMHO) like this
> 
> class BaseField(object):
>     def __init__(self, data):
>         """Default init for the subclasses"""
>         self.data = self.orig = data
> 
> class Field(BaseField):
>     def __init__(self, data):
>         """Another Default init for the subclasses"""
>         super(Field, self).__init__(data)

These two inits together are the original without bad call to 
object.__init__.  No need to do this.

> class IntegerField(Field):
>     def __init__(self, data):
>         """Overridden init"""
>         super(IntegerField, self).__init__(data)
>         self.data = int(data)
> 
> class StringField(Field):
>     pass
> 
> f1 = StringField('abc')
> f2 = IntegerField('10')
> print("f1=%r" % f1.data)
> print("f2=%r" % f2.data)
> print(type(f1))
> print(type(f2))
> 
> Is this a bug or a feature?  Is there a better work-around?

Eliminate bad call.

Terry Jan Reedy



More information about the Python-Dev mailing list