Inheriting from object | |
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 | | | | 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 | | | | 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... | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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 | | | | 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] | | | | 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 | | | | 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 |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,471 network members.
|