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
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com