Connecting Tech Pros Worldwide Forums | Help | Site Map

Inheriting from object

Fuzzyman
Guest
 
Posts: n/a
#1: Jul 19 '05
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


Robert Kern
Guest
 
Posts: n/a
#2: Jul 19 '05

re: Inheriting from object


Fuzzyman wrote:[color=blue]
> 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)
>
> ?[/color]

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

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
rkern@ucsd.edu

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

Bruno Desthuilliers
Guest
 
Posts: n/a
#3: Jul 19 '05

re: Inheriting from object


Fuzzyman a écrit :[color=blue]
> 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)
>
> ?[/color]

Nope.
[color=blue]
> Also, can anyone explain any tangible benefit of inheriting from
> object, when not explicitly using any features of new style classes ?[/color]

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...
Benji York
Guest
 
Posts: n/a
#4: Jul 19 '05

re: Inheriting from object


Fuzzyman wrote:[color=blue]
> Also, can anyone explain any tangible benefit of inheriting from
> object, when not explicitly using any features of new style classes ?[/color]

One reason is that properties won't work correctly.
--
Benji York
Fuzzyman
Guest
 
Posts: n/a
#5: Jul 19 '05

re: Inheriting from object


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

Steven Bethard
Guest
 
Posts: n/a
#6: Jul 19 '05

re: Inheriting from object


Fuzzyman wrote:[color=blue]
> Surely when they are removed :
>
> class foo:
> pass
>
> won't become invalid syntax, it will just automatically inherit from
> object ?[/color]

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
Dave Benjamin
Guest
 
Posts: n/a
#7: Jul 19 '05

re: Inheriting from object


Steven Bethard wrote:[color=blue]
> Guido also suggests that the explicit:
>
> class C(object):
> pass
>
> is "much preferred"[2] over:
>
> __metaclass__ = type
>
> class C:
> pass[/color]

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
Fuzzyman
Guest
 
Posts: n/a
#8: Jul 19 '05

re: Inheriting from object


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

Sion Arrowsmith
Guest
 
Posts: n/a
#9: Jul 19 '05

re: Inheriting from object


Bruno Desthuilliers <bdesth.quelquechose@free.quelquepart.fr> wrote:[color=blue]
>Fuzzyman a écrit :[color=green]
>> *Should* I in fact write :
>>
>> class foo(object):
>> def __init__(self, *args, **kwargs):
>> object.__init__(self)
>>
>> ?[/color]
>Nope.[/color]

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 -- siona@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
Scott David Daniels
Guest
 
Posts: n/a
#10: Jul 19 '05

re: Inheriting from object


Sion Arrowsmith wrote:[color=blue]
> ... 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?
>[/color]
Or, perhaps:
class foo(object):
def __init__(self, *args, **kwargs):
super(foo, self).__init__(self, *args, **kwargs)
...

--Scott David Daniels
Scott.Daniels@Acm.Org
Bengt Richter
Guest
 
Posts: n/a
#11: Jul 19 '05

re: Inheriting from object


On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Scott.Daniels@Acm.Org> wrote:
[color=blue]
>Sion Arrowsmith wrote:[color=green]
>> ... 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?
>>[/color]
>Or, perhaps:
> class foo(object):
> def __init__(self, *args, **kwargs):
> super(foo, self).__init__(self, *args, **kwargs)
> ...
>[/color]
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
Peter Hansen
Guest
 
Posts: n/a
#12: Jul 19 '05

re: Inheriting from object


Bengt Richter wrote:[color=blue]
> 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)[/color]

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
Scott David Daniels
Guest
 
Posts: n/a
#13: Jul 19 '05

re: Inheriting from object


Bengt Richter wrote:[color=blue]
> On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Scott.Daniels@Acm.Org> wrote:[color=green]
>>Or, perhaps:
>> class foo(object):
>> def __init__(self, *args, **kwargs):
>> super(foo, self).__init__(self, *args, **kwargs)
>> ...
>>[/color]
>
> 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)[/color]

Yes, of course (a silly cut-o / paste-o).
[color=blue]
> 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)[/color]

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
Scott.Daniels@Acm.Org
Steven Bethard
Guest
 
Posts: n/a
#14: Jul 19 '05

re: Inheriting from object


Bengt Richter wrote:[color=blue]
> 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 ;-)[/color]

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
John Roth
Guest
 
Posts: n/a
#15: Jul 19 '05

re: Inheriting from object


"Bengt Richter" <bokr@oz.net> wrote in message
news:42c69a4f.336127175@news.oz.net...
[color=blue]
> 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)[/color]

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
[color=blue]
>
> Regards,
> Bengt Richter[/color]

Bengt Richter
Guest
 
Posts: n/a
#16: Jul 19 '05

re: Inheriting from object


On Sat, 02 Jul 2005 14:17:32 -0400, Peter Hansen <peter@engcorp.com> wrote:
[color=blue]
>Bengt Richter wrote:[color=green]
>> 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)[/color]
>
>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.
>[/color]
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 ;-/
[color=blue]
>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[/color]
No danger at all, I'm grateful ;-)

Regards,
Bengt Richter
Bengt Richter
Guest
 
Posts: n/a
#17: Jul 21 '05

re: Inheriting from object


On Sat, 02 Jul 2005 12:26:49 -0700, Scott David Daniels <Scott.Daniels@Acm.Org> wrote:
[color=blue]
>Bengt Richter wrote:[color=green]
>> On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <Scott.Daniels@Acm.Org> wrote:[color=darkred]
>>>Or, perhaps:
>>> class foo(object):
>>> def __init__(self, *args, **kwargs):
>>> super(foo, self).__init__(self, *args, **kwargs)
>>> ...
>>>[/color]
>>
>> 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)[/color]
>
>Yes, of course (a silly cut-o / paste-o).
>[color=green]
>> 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)[/color]
>
>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.
>[/color]
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.,
[color=blue][color=green][color=darkred]
>>> from ut.presets import presets
>>> def foo(): print msg[/color][/color][/color]
...[color=blue][color=green][color=darkred]
>>> foo()[/color][/color][/color]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in foo
NameError: global name 'msg' is not defined[color=blue][color=green][color=darkred]
>>> import dis
>>> dis.dis(foo)[/color][/color][/color]
1 0 LOAD_GLOBAL 0 (msg)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE[color=blue][color=green][color=darkred]
>>> foo = presets(msg='this is a preset')(foo) # manual decoration call
>>> foo()[/color][/color][/color]
this is a preset[color=blue][color=green][color=darkred]
>>> dis.dis(foo)[/color][/color][/color]
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
Closed Thread