[Tutor] metaclass question

Kent Johnson kent37 at tds.net
Wed Jan 24 16:15:06 CET 2007


Kim Branson wrote:
> Hi,
> 
> what i've ended up doing is the following
> 
> define a EmpiricalScore class that has all the methods for computing  
> results
> 
> define a single method in  the evaluation class that is called   
> Score. This method simply walks though a list and executes the  
> methods in that list. There may be one or many.
> 
> 
>      def score(self):
>          """
>          this function computes the interaction energy and returns a
>          dict of key=value pairs for the scoring functions requested
>          """
>          for x in self.functionList:
>              x()
>          return(self.scoreResults)

That looks fine, presumably the functions in functionList affect 
scoreResults...
> 
> The factory class takes as agument some input data and determine  
> which of the methods in the Evaluation class should be called.
> it then produces an instance of the EmpiricalScore class,   (called  
> scoreObject,) and then append the methods from that instance to its  
> internal list.
> 
>          scoreObject=EmpiricalScore()
> 
>          #for each valid scoring function in the functions
>          #tuple we call the method which adds the attribute
>          for x in self.functionsToUse:
>              #we need to check if we want both smog and smogh
>              if x == "smog":
>                  if bothSmog == True:
>                      continue
>                  for y in self.functionsToUse:
>                      if y == "smog_h":
>                          scoreObject.functionList.append 
> (scoreObject.calBothSmog)

This could be much simpler:
if "smog" in self.functionsToUse and "smog_h" in self.functionsToUse:
   scoreObject.functionList.append(scoreObject.calBothSmog)
> 
> This is possibly not the best way to approach this, the factory class  
> is possibly not required and could be added to the  EmpiricalScore  
> class. I think its probably better to separate these to keep things  
> clean.  

 From what you have said I don't see any need for a factory class, it 
sounds like it could be a factory function. You could also put the 
initialization into the EmpiricalScore constructor and just pass the 
list of functions to use to the constructor instead of the factory function.

> In a way this method is constructing a decorator for the  
> EmpiricalScore.score  method.  Is there a way of appending a method  
> to the class after it is initialized.

Yes, you can add a method to a class easily:

In [1]: class Foo(object): pass
    ...:

In [2]: def sayHello(self):
    ...:     print 'Hello'
    ...:

In [3]: f = Foo()

In [4]: f.sayHello()
------------------------------------------------------------
Traceback (most recent call last):
   File "<ipython console>", line 1, in <module>
<type 'exceptions.AttributeError'>: 'Foo' object has no attribute 'sayHello'


In [5]: Foo.sayHello = sayHello

In [6]: f.sayHello()
Hello

However I think you actually want to add a method to an instance, not to 
the class. But the way you have it seems pretty simple.

> Or adding decorators to the  
> method after it is defined?

Yes, you can re-assign a new value to a method which is basically what a 
decorator does. But again it sounds like you want to complicate a clean, 
simple design.

Kent



More information about the Tutor mailing list