473,382 Members | 1,252 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

super. could there be a simpler super?

Hello!

Always when I use "super" I create a code duplication because class
used as first arg to "super" is always the class where the method
containing "super" was defined in:
'''
class C:
def method(self):
super(C, self).method()
'''

Obviously the methods like the one below doesn't work "right";-)
'''
def super(self):
super(self.__class__, self)
class C:
def method(self):
super(self).method()
'''

Is it possible that such a "super"(deducing class method declaration
context) could appear in Python?
(It seems to me that to implement a simple super something should be
done during "compilation" of class declaration.)

Best regards,
Kerim mailto:wa****@hotbox.ru

Jul 18 '05 #1
4 2298
Kerim Borchaev <wa****@hotbox.ru>:
Is it possible that such a "super"(deducing class method declaration
context) could appear in Python?
(It seems to me that to implement a simple super something should be
done during "compilation" of class declaration.)


The document "Unifying types and classes in Python 2.2" by Guido
probably answers your question.

Quote from http://www.python.org/2.2.3/descrintro.html#cooperation
regarding super:

"It would be nice if we didn't have to name the class explicitly, but
this would require more help from Python's parser than we can
currently get. I hope to fix this in a future Python release by making
the parser recognize super."

--
Kristian Ovaska - http://www.cs.helsinki.fi/u/hkovaska/en/
Jul 18 '05 #2
On Thu, 15 Jan 2004 11:50:57 +0300, Kerim Borchaev <wa****@hotbox.ru>
wrote:
Hello!

Always when I use "super" I create a code duplication because class
used as first arg to "super" is always the class where the method
containing "super" was defined in:
'''
class C:
def method(self):
super(C, self).method()
'''

Obviously the methods like the one below doesn't work "right";-)
'''
def super(self):
super(self.__class__, self)
class C:
def method(self):
super(self).method()
'''


Hmm... I once used super where the class used as first arg was *not*
the class defining the method, it was it's super class. So I was
calling, not the super method, but it's grand-super method.

Arguably, this is a clear sign of bad design on my part. But that's
how it went, anyway.

With my best regards,
G. Rodrigues

Jul 18 '05 #3
Kristian Ovaska wrote:
Kerim Borchaev <wa****@hotbox.ru>:
Is it possible that such a "super"(deducing class method declaration
context) could appear in Python?
(It seems to me that to implement a simple super something should be
done during "compilation" of class declaration.)


The document "Unifying types and classes in Python 2.2" by Guido
probably answers your question.

Quote from http://www.python.org/2.2.3/descrintro.html#cooperation
regarding super:

"It would be nice if we didn't have to name the class explicitly, but
this would require more help from Python's parser than we can
currently get. I hope to fix this in a future Python release by making
the parser recognize super."


Another quote from the same page :) :

--- start quote ---
Our second example creates a class, 'autosuper', which will add a
private class variable named __super, set to the value super(cls).
(Recall the discussion of self.__super above.) Now, __super is a private
name (starts with double underscore) but we want it to be a private name
of the class to be created, not a private name of autosuper. Thus, we
must do the name mangling ourselves, and use setattr() to set the class
variable. For the purpose of this example, I'm simplifying the name
mangling to "prepend an underscore and the class name". Again, it's
sufficient to override __init__ to do what we want, and again, we call
the base class __init__ cooperatively.

class autosuper(type):
def __init__(cls, name, bases, dict):
super(autosuper, cls).__init__(name, bases, dict)
setattr(cls, "_%s__super" % name, super(cls))

Now let's test autosuper with the classic diamond diagram:

class A:
__metaclass__ = autosuper
def meth(self):
return "A"
class B(A):
def meth(self):
return "B" + self.__super.meth()
class C(A):
def meth(self):
return "C" + self.__super.meth()
class D(C, B):
def meth(self):
return "D" + self.__super.meth()

assert D().meth() == "DCBA"

(Our autosuper metaclass is easily fooled if you define a subclass with
the same name as a base class; it should really check for that condition
and raise an error if it occurs. But that's more code than feels right
for an example, so I'll leave it as an exercise for the reader.)

--- end quote ---

yours,
Gerrit.
--
164. If his father-in-law do not pay back to him the amount of the
"purchase price" he may subtract the amount of the "Purchase price" from
the dowry, and then pay the remainder to her father's house.
-- 1780 BC, Hammurabi, Code of Law
--
PrePEP: Builtin path type
http://people.nl.linux.org/~gerrit/c.../pep-xxxx.html
Asperger's Syndrome - a personal approach:
http://people.nl.linux.org/~gerrit/english/

Jul 18 '05 #4
Kerim Borchaev <wa****@hotbox.ru> wrote in message news:<ma**************************************@pyt hon.org>...
Hello!

Always when I use "super" I create a code duplication because class
used as first arg to "super" is always the class where the method
containing "super" was defined in:
'''
class C:
def method(self):
super(C, self).method()
'''

Obviously the methods like the one below doesn't work "right";-)
'''
def super(self):
super(self.__class__, self)
class C:
def method(self):
super(self).method()
'''

Is it possible that such a "super"(deducing class method declaration
context) could appear in Python?
(It seems to me that to implement a simple super something should be
done during "compilation" of class declaration.)

Best regards,
Kerim mailto:wa****@hotbox.ru


``super`` is one of the trickiest Python constructs. In
http://www.python.org/2.2.3/descrintro.html Guido sketches
a metaclass solution which however is not quite satisfactory (for one,
it does not work with magic methods).

Some time ago I went to "fix" autosuper, but that required a major metaclass
hacking which was so deep that I have already forgotten what I did ;)
Nevertheless, I have still the files around, and my test suite runs okay
(this only means that the bugs are smarter than me) so I think I will post
the code. If somebody uses it and finds an unexpected behavior, please
send me a note. If somebody wants his head to explode, please try to
understand what safetype does ;)

Here are two examples of usage:

# example1.py: the diamond diagram

from super import autosuper

class A(object):
__metaclass__=autosuper
def m(self):
return "A"
class B(A):
def m(self):
return "B" + self.__super.m()
class C(A):
def m(self):
return "C" + self.__super.m()
class D(C, B):
def m(self):
return "D" + self.__super.m()

print D().m()

this prints DCBA.

#example2.py

from super import autosuper

class A(str):
__metaclass__=autosuper
def __new__(cls):
obj='A'+cls.__super.__new__(cls)
print obj
return obj
class B(A):
def __new__(cls):
obj="B" + cls.__super.__new__(cls)
print obj
return obj
class C(A):
def __new__(cls):
obj="C" + cls.__super.__new__(cls)
print obj
return obj
class D(C, B):
def __new__(cls):
obj="D" + cls.__super.__new__(cls)
print obj
return obj

D()

this prints

A
BA
CBA
DCBA

Here is the module super.py:

# super.py

from safetype import safetype # deep magic to avoid metaclass conflicts

class _super(object):
"""Helper descriptor, called by the ``Enable__super`` metaclass which will
take care of defining the ``__thisclass__`` attribute; it should not be
called directly, unless you really know what you are doing. Notice that
this ``_super`` is minimal, i.e. it does not define ``__new__``,
`` __init__`` or other special methods; this avoids the problems of the
standard ``super``."""
def __get__(self,obj,klass):
if obj is None: obj=klass
return super(self.__thisclass__,obj)

class autosuper(safetype):
"""Cooperative safe metaclass which defines a private attribute ``__super``
on its instances, containing a reference to the descriptor ``_super``.
This enable the cooperative syntax ``obj.__super.methodname`` as
sugar for ``super(callingclass,obj).methodname``."""
def __init__(cls,*args):
super(autosuper,cls).__init__(*args)
if len(args)==1 or args[0]=='superobject': return # do nothing
strippedname=args[0].lstrip('_')
# if the class name starts with underscores, they must
# be stripped; this is how the mangling mechanism works
sup=_super(); sup.__thisclass__=cls # trick to avoid __init__ in _super
setattr(cls,'_%s__super' % strippedname,sup)

Here is the module safetype.py:

# safetype.py

"""Deep, **DEEP** magic to remove metaclass conflicts.

``safetype`` provides the ``safetype`` metaclass, the mother of conflict-free
metaclasses. The suggested import syntax for usage in other modules is

from safetype import safetype as type

If you override ``__new__`` when you derive from ``safetype``,
you should do it cooperatively.

Example:
from safetype import type class M(type): .... def __new__(mcl,*args):
.... print 'creating a class from M'
.... return super(M,mcl).__new__(mcl,*args)
class N(type): .... def __new__(mcl,*args):
.... print 'creating a class from N'
.... return super(N,mcl).__new__(mcl,*args)
class C: .... __metaclass__=M
creating a class from M
class D: .... __metaclass__=N
creating a class from N
class E(C,D): .... pass
creating a class from M
creating a class from N
E.__class__ # automagically created <class 'safetype.MN'> E.__metaclass__ # inherited from C <class 'M'>
"""

import sys,sets,types,__builtin__

__type__=__builtin__.type
#the aboriginal 'type'; useful if you rebinds 'type' to 'safetype'

metadic={} # associates tuple of bases metaclasses to children metaclasses

class safetype(type):
"""Overrides the ``__new__`` method of the ``type`` metaclass, making the
generation of classes conflict-proof."""
# Seventeen lines of DENSE code!
def __new__(mcl,*args):
nargs=len(args)
if nargs==1: # works as __builtin__.type
return __type__(args[0])
elif nargs==3: # creates the class using the appropriate metaclass
n,b,d = args # name, bases and dictionary
mb=map(__type__,b) # metaclasses of the bases
meta=generatemetaclass([mcl,]+mb) # recursive
if mcl is meta: # meta is trivial, dispatch to the default __new__
return super(safetype,mcl).__new__(mcl,n,b,d)
elif is_less_specific(mcl,mb): # dispatch to meta.__new__
return meta.__new__(meta,n,b,d)
else: # non-trivial metaclass, dispatch to the right __new__
# (it will take a second round)
return super(mcl,meta).__new__(meta,n,b,d)
else:
raise TypeError('%s() takes 1 or 3 arguments' % mcl.__name__)

def generatemetaclass(metas):
"""Given a sequence of metaclasses, removes redundances and, if needed,
creates a new metaclass; returns the metaclass and updates the global
dictionary.of metaclasses. If the metaclass is already in the dictionary,
simply retrieves it."""

metabases=remove_redundant(metas)# metas have the priority
if metabases in metadic: # already generated metaclass
return metadic[metabases]
elif len(metabases)==1: # single metabase
meta=metabases[0]
else: # multiple metabases
metaname=''.join([m.__name__ for m in metabases])
meta=safetype(metaname,metabases,{})
return metadic.setdefault(metabases,meta)

def is_less_specific(c,ls):
"c is an ancestor of (at least) one class in the list ls."
for C in ls:
if issubclass(C,c) and C is not c: return True
return False

def remove_redundant(bases):
"""Returns a tuple of non-redundant base classes.
Given a sequence of base classes, a class is redundant if

1. it is duplicated;
2. it is implied by the others, i.e. it is an ancestor of at least one
of the other classes;
3. it is ClassType, the metaclass of old style classes.

For instance, if ``C`` is derived from ``B``, in the
sequence ``C,B`` the class ``B`` is redundant, since all its features are
already provided by ``C``. Therefore ``B``
is removed and ``remove_redundant`` returns the tuple ``(C,)``:
class B(object): pass ... class C(B): pass ... import safetype; safetype.remove_redundant([C,B])

(<class 'C'>,)
"""
redundant=sets.Set((types.ClassType,)) # old style metaclass
ls=list(bases)
for c in bases:
if is_less_specific(c,ls) or c in redundant:
ls.remove(c)
else: # c is a redundant class to be removed if found
redundant.add(c)
return tuple(ls)
Jul 18 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Clarence Gardner | last post by:
The super object is considered a solution to the "diamond problem". However, it generally requires that the ultimate base class know that it is last in the method resolution order, and hence it...
11
by: Nicolas Lehuen | last post by:
Hi, I hope this is not a FAQ, but I have trouble understanding the behaviour of the super() built-in function. I've read the excellent book 'Python in a Nutshell' which explains this built-in...
0
by: Delaney, Timothy C (Timothy) | last post by:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286195 This is a new version of super that automatically determines which method needs to be called based on the existing stack frames....
6
by: Steven Bethard | last post by:
When would you call super with only one argument? The only examples I can find of doing this are in the test suite for super. Playing around with it: py> class A(object): .... x = 'a'...
2
by: Michael P. Soulier | last post by:
Ok, this works in Python on Windows, but here on Linux, with Python 2.4.1, I'm getting an error. The docs say: A typical use for calling a cooperative superclass method is: class C(B):...
7
by: Kent Johnson | last post by:
Are there any best practice guidelines for when to use super(Class, self).__init__() vs Base.__init__(self) to call a base class __init__()? The super() method only works correctly in multiple...
7
by: Pupeno | last post by:
Hello, I have a class called MyConfig, it is based on Python's ConfigParser.ConfigParser. It implements add_section(self, section), which is also implemented on ConfigParser.ConfigParser, which I...
4
by: Noah | last post by:
Am I the only one that finds the super function to be confusing? I have a base class that inherits from object. In other words new style class: class foo (object): def __init__ (self, arg_A,...
12
by: iu2 | last post by:
Hi I'm trying to make a method call automatically to its super using this syntax: class A: chained = def pr(self): print 'Hello from A'
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.