By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,399 Members | 886 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,399 IT Pros & Developers. It's quick & easy.

Inheriting from object

P: n/a
Hello,

To create a classic (old style) class, I write :

class foo:
pass

To do the equivalent as a new style class, I write :

class foo(object):
pass

*Should* I in fact write :

class foo(object):
def __init__(self, *args, **kwargs):
object.__init__(self)

?

Also, can anyone explain any tangible benefit of inheriting from
object, when not explicitly using any features of new style classes ?

Thanks :-)

Fuzzyman
http://www.voidspace.org.uk/python

Jul 19 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Fuzzyman wrote:
Hello,

To create a classic (old style) class, I write :

class foo:
pass

To do the equivalent as a new style class, I write :

class foo(object):
pass

*Should* I in fact write :

class foo(object):
def __init__(self, *args, **kwargs):
object.__init__(self)

?
I don't believe so.
Also, can anyone explain any tangible benefit of inheriting from
object, when not explicitly using any features of new style classes ?


This class might not, but you (or someone else) may decide later to
subclass it and want to use those features. It's a good habit to get
into even if you don't initially plan on using those features.

--
Robert Kern
rk***@ucsd.edu

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter

Jul 19 '05 #2

P: n/a
Fuzzyman a écrit :
Hello,

To create a classic (old style) class, I write :

class foo:
pass

To do the equivalent as a new style class, I write :

class foo(object):
pass

*Should* I in fact write :

class foo(object):
def __init__(self, *args, **kwargs):
object.__init__(self)

?
Nope.
Also, can anyone explain any tangible benefit of inheriting from
object, when not explicitly using any features of new style classes ?


old-style classes are deprecated. They are still in the language (for
how much time ?) for compatibility reasons, but they won't last forever.
That should be a good enough reason to avoid them, given that the
only thing you have to do is to inherit from object...
Jul 19 '05 #3

P: n/a
Fuzzyman wrote:
Also, can anyone explain any tangible benefit of inheriting from
object, when not explicitly using any features of new style classes ?


One reason is that properties won't work correctly.
--
Benji York
Jul 19 '05 #4

P: n/a
So theres no actual advantage that you know of ;-)

Surely when they are removed :

class foo:
pass

won't become invalid syntax, it will just automatically inherit from
object ?

That's what I assumed, anyway....

Regards,

Fuzz
http://www.voidspace.org.uk/python

Jul 19 '05 #5

P: n/a
Fuzzyman wrote:
Surely when they are removed :

class foo:
pass

won't become invalid syntax, it will just automatically inherit from
object ?


Well, Guido views this particular syntax as an "oopsie"[1]. It should
actually look like:

class C():
pass

Guido also suggests that the explicit:

class C(object):
pass

is "much preferred"[2] over:

__metaclass__ = type

class C:
pass

when creating new-style classes. It's not exactly clear where Guido
comes down on your particular issue, but if I had to guess, I would
guess that he prefers the explicit reference to "object".

STeVe

[1]http://mail.python.org/pipermail/python-dev/2005-February/051706.html
[2]http://mail.python.org/pipermail/python-dev/2005-February/051711.html
Jul 19 '05 #6

P: n/a
Steven Bethard wrote:
Guido also suggests that the explicit:

class C(object):
pass

is "much preferred"[2] over:

__metaclass__ = type

class C:
pass


Really? I have been toying with the idea of using the __metaclass__
trick, since it results in completely valid Jython 2.1 code, as long as
you don't use any of the new-style features.

But once Brian Zimmer gets his broadband fixed, we're supposed to get a
new alpha release. =)

Dave
Jul 19 '05 #7

P: n/a
The reason I ask is that I often (well... a couple of times anyway) see
cryptic omments like :

and if you inherit from object you get all the benefits of new
style classes

Now I know about the advantages of inheriting from the built in types
(if that's what you want to do) -but am a bit fuzzier on the 'general
benefits'.

I'm vaguely aware of properties.... I'll have to explore them at some
point.

Best Regards,

Fuzzy
http://www.voidspace.org.uk/python

Jul 19 '05 #8

P: n/a
Bruno Desthuilliers <bd*****************@free.quelquepart.fr> wrote:
Fuzzyman a écrit :
*Should* I in fact write :

class foo(object):
def __init__(self, *args, **kwargs):
object.__init__(self)

?

Nope.


And if you were to do so, surely:

class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self)

would be the preferred way to go?

--
\S -- si***@chiark.greenend.org.uk -- http://www.chaos.org.uk/~sion/
___ | "Frankly I have no feelings towards penguins one way or the other"
\X/ | -- Arthur C. Clarke
her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump
Jul 19 '05 #9

P: n/a
Sion Arrowsmith wrote:
... And if you were to do so, surely:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self)

would be the preferred way to go?

Or, perhaps:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self, *args, **kwargs)
...

--Scott David Daniels
Sc***********@Acm.Org
Jul 19 '05 #10

P: n/a
On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Sc***********@Acm.Org> wrote:
Sion Arrowsmith wrote:
... And if you were to do so, surely:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self)

would be the preferred way to go?

Or, perhaps:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self, *args, **kwargs)
...

Doesn't super(foo, self).__init__ return a bound method, so you don't
need to pass self again? I.e.,
super(foo, self).__init__(*args, **kwargs)

BTW, there's something about referring to type(self) by its not
always dependably bound (though usually global) name that bothers me.

I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)

(I think Michele Simionato may have posted some idea like this early on that
I didn't really follow, but maybe my subconscious snagged and garbled ;-)

Regards,
Bengt Richter
Jul 19 '05 #11

P: n/a
Bengt Richter wrote:
BTW, there's something about referring to type(self) by its not
always dependably bound (though usually global) name that bothers me.

I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)


This doesn't work: type(self) is always the type of the instantiated
(child) class, not the type of the class at whatever level of the class
hierarchy the __init__() calls currently have reached.

In other words, with these definitions:

class A(object):
def __init__(self):
super(type(self), self).__init__() # does not do what you want

class B(A):
def __init__(self):
super(type(self), self).__init__() # works okay here

if you do "b = B()", the first __init__ will work (i.e. B's __init__
will find and call A.__init__), but the next one won't (i.e. A.__init__
will now try calling A.__init__ recursively, giving you an eventual
stack overflow).

-correcting-bengt-richter-on-such-arcana-is-always-dangerously y'rs,
Peter
Jul 19 '05 #12

P: n/a
Bengt Richter wrote:
On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Sc***********@Acm.Org> wrote:
Or, perhaps:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self, *args, **kwargs)
...

Doesn't super(foo, self).__init__ return a bound method, so you don't
need to pass self again? I.e.,
super(foo, self).__init__(*args, **kwargs)


Yes, of course (a silly cut-o / paste-o).
BTW, there's something about referring to type(self) by its not
always dependably bound (though usually global) name that bothers me.

I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)


The problem with this is:

class A(object):
def __init__(self, *args, **kwargs):
print 'Set A(*%r, **%r)' % (args, kwargs)
class B(A):
def __init__(self, *args, **kwargs):
print 'Set B(*%r, **%r)' % (args, kwargs)
super(B, self).__init__(*args, **kwargs)
class C(B):
def __init__(self, *args, **kwargs):
print 'Set C(*%r, **%r)' % (args, kwargs)
super(C, self).__init__(*args, **kwargs)

class D(A):
def __init__(self, *args, **kwargs):
print 'Set D(*%r, **%r)' % (args, kwargs)
super(type(self), self).__init__(*args, **kwargs)
class E(D):
def __init__(self, *args, **kwargs):
print 'Set E(*%r, **%r)' % (args, kwargs)
super(type(self), self).__init__(*args, **kwargs)
You'll see the problem when you attempt to create an instance of E.
All of the others work just fine.

--Scott David Daniels
Sc***********@Acm.Org
Jul 19 '05 #13

P: n/a
Bengt Richter wrote:
I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)

(I think Michele Simionato may have posted some idea like this early on that
I didn't really follow, but maybe my subconscious snagged and garbled ;-)


Here's the link I believe you're referring to:
http://groups-beta.google.com/group/...34684c138cf9f3

Probably worth reading for anyone interested in making super syntax
"look prettier". Basically Michele shows that the current super()
object fails in a number of ways when you try to make it a class attribute.

STeVe
Jul 19 '05 #14

P: n/a
"Bengt Richter" <bo**@oz.net> wrote in message
news:42****************@news.oz.net...
I wonder if the above common use of super could be implemented as a
property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it
self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)
Well, let's look at it. If I implemented a super() method on
object (and I didn't shadow it anywhere) what I'd have when
it was invoked is something like

def super(self):
stuff

From there one could get the current instance's class, so
we've got all the ingredients of the regular super(class, instance)
built-in function. What it wouldn't have is the ability to invoke it
on an arbitrary class and instance.

The big issue seems to be the direction Guido wants to take
Python - he seems to not want to put methods on the
object type. I have to say that I don't understand his reasoning,
if that is indeed his position.

John Roth

Regards,
Bengt Richter


Jul 19 '05 #15

P: n/a
On Sat, 02 Jul 2005 14:17:32 -0400, Peter Hansen <pe***@engcorp.com> wrote:
Bengt Richter wrote:
BTW, there's something about referring to type(self) by its not
always dependably bound (though usually global) name that bothers me.

I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)
This doesn't work: type(self) is always the type of the instantiated
(child) class, not the type of the class at whatever level of the class
hierarchy the __init__() calls currently have reached.

D'oh, you're right, that was too easy a property definition ;-/
I still don't like having to use a global name to get access to the
current lexical scope object though. But I can't think of a decent hack
right now to get around all that, and I can't spend too much time ;-/
In other words, with these definitions:

class A(object):
def __init__(self):
super(type(self), self).__init__() # does not do what you want

class B(A):
def __init__(self):
super(type(self), self).__init__() # works okay here

if you do "b = B()", the first __init__ will work (i.e. B's __init__
will find and call A.__init__), but the next one won't (i.e. A.__init__
will now try calling A.__init__ recursively, giving you an eventual
stack overflow).

-correcting-bengt-richter-on-such-arcana-is-always-dangerously y'rs,
Peter

No danger at all, I'm grateful ;-)

Regards,
Bengt Richter
Jul 19 '05 #16

P: n/a
On Sat, 02 Jul 2005 12:26:49 -0700, Scott David Daniels <Sc***********@Acm.Org> wrote:
Bengt Richter wrote:
On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Sc***********@Acm.Org> wrote:
Or, perhaps:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self, *args, **kwargs)
...


Doesn't super(foo, self).__init__ return a bound method, so you don't
need to pass self again? I.e.,
super(foo, self).__init__(*args, **kwargs)


Yes, of course (a silly cut-o / paste-o).
BTW, there's something about referring to type(self) by its not
always dependably bound (though usually global) name that bothers me.

I wonder if the above common use of super could be implemented as a property of object,
so you'd normally inherit it and be able to write
self.super.__init__(*args, **kwargs) # (maybe spell it self.__super__.__init__(...) I suppose)

I.e., self.__super__ would effectively return the equivalent of
super(type(self), self)


The problem with this is:

class A(object):
def __init__(self, *args, **kwargs):
print 'Set A(*%r, **%r)' % (args, kwargs)
class B(A):
def __init__(self, *args, **kwargs):
print 'Set B(*%r, **%r)' % (args, kwargs)
super(B, self).__init__(*args, **kwargs)
class C(B):
def __init__(self, *args, **kwargs):
print 'Set C(*%r, **%r)' % (args, kwargs)
super(C, self).__init__(*args, **kwargs)

class D(A):
def __init__(self, *args, **kwargs):
print 'Set D(*%r, **%r)' % (args, kwargs)
super(type(self), self).__init__(*args, **kwargs)
class E(D):
def __init__(self, *args, **kwargs):
print 'Set E(*%r, **%r)' % (args, kwargs)
super(type(self), self).__init__(*args, **kwargs)
You'll see the problem when you attempt to create an instance of E.
All of the others work just fine.

Ok, I had a brain-o ;-) If we had class decorators analogous to function decorators,
we could write
@deco(args)
class X: ...

instead of
class X: ...
X = deco(args)(X)

below, but anyway (untested beond what you see), using your example, have a look:

----< super_cls_deco.py >-------------------------------------------------------
# super_cls_deco.py -- bokr 2005-07-03
from ut.presets import presets # function local presets decorator
def preset_super_ubm(target_method_name, super_method_name, alias=None):
"""
class decorator to preset an unbound super-method as a local
alias name in a target method of the decorated class.
"""
if alias is None: alias = 'SUPER'+super_method_name # for local name in target method
def super_deco(cls):
if not getattr(cls, target_method_name):
raise ValueError, 'class %s does not have a %s method' %(
cls.__name__, target_method_name)
for base in cls.mro()[1:]:
if hasattr(base, super_method_name):
ubm = getattr(base, super_method_name)
setattr(cls, target_method_name, presets(**{alias:ubm})(
cls.__dict__[target_method_name]))
return cls
raise ValueError, '%s not found as super-method' % super_method_name
return super_deco

def test():
class A(object):
def __init__(self, *args, **kwargs):
print 'Set A(*%r, **%r)' % (args, kwargs)
SUPER__init__(self, *(('from A:',)+args), **kwargs)
A = preset_super_ubm('__init__', '__init__')(A)
class B(A):
def __init__(self, *args, **kwargs):
print 'Set B(*%r, **%r)' % (args, kwargs)
SUPER__init__(self, *(('from B:',)+args), **kwargs)
#super(B, self).__init__(*args, **kwargs)
B = preset_super_ubm('__init__', '__init__')(B)

class C(B):
def __init__(self, *args, **kwargs):
print 'Set C(*%r, **%r)' % (args, kwargs)
SUPER__init__(self, *(('from C:',)+args), **kwargs)
#super(C, self).__init__(*args, **kwargs)
C = preset_super_ubm('__init__', '__init__')(C)

class D(A):
def __init__(self, *args, **kwargs):
print 'Set D(*%r, **%r)' % (args, kwargs)
SUPER__init__(self, *(('from D:',)+args), **kwargs)
#super(type(self), self).__init__(*args, **kwargs)
D = preset_super_ubm('__init__', '__init__')(D)

class E(D):
def __init__(self, *args, **kwargs):
print 'Set E(*%r, **%r)' % (args, kwargs)
SUPER__init__(self, *(('from E:',)+args), **kwargs)
#super(type(self), self).__init__(*args, **kwargs)
E = preset_super_ubm('__init__', '__init__')(E)

print '... from creating instance %s\n' % A('some', 'args', a='keyword')
print '... from creating instance %s\n' % B('some', 'args', a='keyword')
print '... from creating instance %s\n' % C('some', 'args', a='keyword')
print '... from creating instance %s\n' % D('some', 'args', a='keyword')
print '... from creating instance %s\n' % E('some', 'args', a='keyword')

if __name__ == '__main__':
test()
--------------------------------------------------------------------------------

which results in:

[11:45] C:\pywk\clp>py24 super_cls_deco.py
Set A(*('some', 'args'), **{'a': 'keyword'})
.... from creating instance <__main__.A object at 0x02F031EC>

Set B(*('some', 'args'), **{'a': 'keyword'})
Set A(*('from B:', 'some', 'args'), **{'a': 'keyword'})
.... from creating instance <__main__.B object at 0x02F031EC>

Set C(*('some', 'args'), **{'a': 'keyword'})
Set B(*('from C:', 'some', 'args'), **{'a': 'keyword'})
Set A(*('from B:', 'from C:', 'some', 'args'), **{'a': 'keyword'})
.... from creating instance <__main__.C object at 0x02F031EC>

Set D(*('some', 'args'), **{'a': 'keyword'})
Set A(*('from D:', 'some', 'args'), **{'a': 'keyword'})
.... from creating instance <__main__.D object at 0x02F031EC>

Set E(*('some', 'args'), **{'a': 'keyword'})
Set D(*('from E:', 'some', 'args'), **{'a': 'keyword'})
Set A(*('from D:', 'from E:', 'some', 'args'), **{'a': 'keyword'})
.... from creating instance <__main__.E object at 0x02F031EC>

(presets is my function byte-code-hacking decorator that presets local names
in a function at decoration-time without using the default-argument hack)
E.g.,
from ut.presets import presets
def foo(): print msg ... foo() Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in foo
NameError: global name 'msg' is not defined import dis
dis.dis(foo) 1 0 LOAD_GLOBAL 0 (msg)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE foo = presets(msg='this is a preset')(foo) # manual decoration call
foo() this is a preset dis.dis(foo)

1 0 LOAD_CONST 1 ('this is a preset')
3 STORE_FAST 0 (msg)

3 6 LOAD_FAST 0 (msg)
9 PRINT_ITEM
10 PRINT_NEWLINE
11 LOAD_CONST 0 (None)
14 RETURN_VALUE

A class decorator would avoid that nasty global name reference that bothers me ;-)

Regards,
Bengt Richter
Jul 21 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.