On Sat, 02 Jul 2005 12:26:49 -0700, Scott David Daniels <[EMAIL PROTECTED]> wrote:
>Bengt Richter wrote: >> On Thu, 30 Jun 2005 08:54:31 -0700, Scott David Daniels <[EMAIL PROTECTED]> >> 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 -- http://mail.python.org/mailman/listinfo/python-list