Obtaining a callable class method object from a specific class

Arnaud Delobelle arnodel at googlemail.com
Thu Apr 10 16:08:30 EDT 2008


On Apr 10, 7:47 pm, Nathan Duran <co... at khiltd.com> wrote:
> This is a contrived pseudocode example which has been broken out of a  
> larger problem, so it may seem like a strange thing to want to do,  
> but...
>
> I have a group of objects which inherit (single) from a common base  
> class like so:
>
> ---
> class Root(object):
>      @classmethod
>      def CumulativeScore(cls, arg):
>          #Ask every child class to
>          #generate a score and add
>          #them together
>          cumulativescore = 0
>          for base in cls.mro():
>              cumulativescore += base.Score(arg)
>          return cumulativescore
>      #No Score method defined in Root so don't try to call one!
>
> class BranchChild(Root):
>      @classmethod
>      def Score(cls, arg):
>          return 1
>
> class LeafChild(BranchChild):
>      @classmethod
>      def Score(cls, arg):
>          return 3
>
> class LeafChild2(BranchChild):
>      pass
>      #No Score method defined here, either!
>

I won't question why you want to do this...
Here is a solution base on a metaclass, but it feels wrong.

@classmethod
def score(cls, args):
    return 0

def totalscore(rootcls, arg):
    return sum(cls.score(arg) for cls in rootcls.mro()
               if hasattr(cls, 'score'))

class MetaScore(type):
    def __new__(meta, name, bases, attrs):
        attrs.setdefault('score', score)
        return type.__new__(meta, name, bases, attrs)

class Root(object):
    __metaclass__ = MetaScore

class Branch(Root):
    @classmethod
    def score(cls, arg):
        return 1

class Leaf(Branch):
    @classmethod
    def score(cls, arg):
        return 3

class Leaf2(Branch):
    pass

--------- Test ---------

>>> totalscore(Root, 1)
0
>>> totalscore(Branch, 1)
1
>>> totalscore(Leaf, 1)
4
>>> totalscore(Leaf2, 1)
1

--
Arnaud




More information about the Python-list mailing list