[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