Access to static members from inside a method decorator?

Bruno Desthuilliers onurb at xiludom.gro
Thu Oct 5 05:00:42 EDT 2006


glen.coates.bigworld at gmail.com wrote:
> I'm developing a library at the moment that involves many classes, some
> of which have "exposed" capabilities.  I'm trying to design a nice
> interface for both exposing those capabilities, and inspecting
> instances to find out what capabilities they have.
> 
> At the moment, I'm leaning towards a superclass (Exposed) that defines
> a static method which is a decorator (expose) such that any derived
> class can mark a method with @Exposed.expose and it will then be later
> returned by getExposedMethods(), a la:
> 
> class Exposed:
>   @staticmethod
>   def expose( f ):
>     ...
> 
>   def getExposedMethods( self ):
>     ...
> 
> class Person( Exposed ):
>   @Exposed.expose
>   def talk( self, ... ):
>     ...
> 
> I'm trying to implement the decorator by having it populate a static
> member list of whatever class it's in with a reference to the method.
> getExposedMethods() would then return the contents of each of those
> lists from itself back to Exposed in the class hierarchy.  The first
> problem was that having a reference to the method (i.e. talk()) does
> not allow you to get a reference to the enclosing class (I had hoped
> im_class would lead me there). 

Not yet. When your decorator is called, the class object is not yet
created, and what you are decorating is a plain function.

> The real hiccup was that explicitly
> passing the class as an argument to the decorator generates a undefined
> global name error, presumably because at that point of execution the
> class object hasn't been fully created/initialised.

Exactly.

> So how can this be done? 

The simplest thing is to use a two-stages scheme : mark the functions as
exposed, then collect them:

def expose(func):
  func._exposed = True
  return func

def exposed(obj):
  return callable(obj) and getattr(obj, '_exposed', False)

class Exposing(object):
  @classmethod
  def get_exposed_methods(cls):
    try:
      exposeds = cls._exposed_methods
    except AttributeError:
      exposeds = []
      for name in dir(cls):
        obj = getattr(cls, name)
        if exposed(obj):
          exposeds.append(obj)
      cls._exposed_methods = exposeds
    return exposeds

class Parrot(Exposing):
  @expose
  def parrot(self, what):
    return "%s says %s" % (self, str(what))



HTH
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list