@classmethod question

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Thu Apr 24 10:46:25 CEST 2008


Scott SA a écrit :
> Hi,
> 
> I'm using the @classemethod decorator for some convenience methods
> and for some reason, either mental block or otherwise, can't seem to
> figure out how to elegantly detect if the call is from an instance or
> not.
Well, the point is that a classmethod *always* receive the class as 
first argument, wether it's called on the class or an instance. If 
that's not what you want, then you don't use the right tool.


> Here's the problem: Within the class definition, 'isinstance' has
nothing to compare to because the class does not appear to exist.
> 
> This is NOT a great example, but it outlines the the code: >
>     class RecipieClass:
>         def __init__(self):
>             pass
>         
>         @classmethod
>         def get_ingrendients(self, recipie_list=None):
>             
>             if isinstnace(self,RecipieClass):
>                 return self.do_something_interesting()
>             else:
>                 return do_something_boring(recipie_list)
> 
> Yes, I can test to see if the param exists, but that makes the call
> exclusive i.e. I can _only_ call it as an instance or with a parameter.
> 
> Why am I doing this?
> 
> It is a series of convenience methods, in this case I'm interacting
> with a database via an ORM (object-relational model).

out of curiosity : which one ?

> I want the ability
> to call a class-ojbect and get related values, or pass some criteria and
> get related values for them without collecting the records first as
> instances, then iterating them. I need to call this from several places
> so I want to be DRY (don't repeat yourself).
> 
> The easiest way to describe this as an analogy would be like having a
> recipie for cookies and wanting to know all of the ingredients ahead of
> time. Then, at another time, wanting to know what all the ingredients
> would be to make cookies, cake and bread (i.e. complete shopping list).

>   cookie_recipie = RecipieClass.get_recipie('cookies')
>   cookie_recipie.get_ingredients()
>         2C Flour
>         0.5 C Sugar
>         ...
>         
>   RecipieClass.get_ingrendients(['cookies','cake','bread'])
>         8C Flour
>         2C Sugar
>         ...

 > Of course any suggestions on how this might be better approached 
would > be interesting too.

Why do you want the same method to do two different things ? You clearly 
have two distincts methods doing different things here, and as a user of 
  your code I'd find your API confusing. May I suggest a much simpler 
approach:


class Recipies(object):
     @property
     def ingredients(self):
         return <dict of ingredient:qty for self>

     @classmethod
     def get_ingredients_for(cls, *id_recipies):
         return <dict of ingredient:summed_qty for all id_recipies>


print Recipie.get('cookie').ingredients
print Recipies.get_ingredients_for('cookie', 'cake', 'bread')

My 2 cents...



More information about the Python-list mailing list