On 24 апр, 07:27, Scott SA <[EMAIL PROTECTED]> wrote: > 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. > > 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). 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. > > TIA, > > Scott
Hi, It would make sense to separate instance-level and class-level behaviour with additional 'objects' namespace. e.g. cookie_recipie.get_ingredients() to get ingredients only for cookie recipie and RecipieClass.objects.get_ingrendients([....]) to get all the ingredients. The elegant solution (AFAIK used by Django) would be to use metaclass and the object with custom descriptor for class-object/table level stuff. Something like this: class RecipieMetaclass(type): def __new__(cls, bases, attrs): new_cls = type.__new__(cls, name, bases, attrs) new_cls.objects = IngredientsDescriptor(IngredientsManager()) return new_cls class RecipieClass(object): __metaclass__ = RecipieMetaclass def get_ingredients(self, recipie_list=None): return self.do_something_interesting(recipie_list) class IngredientsManager(object): def get_ingredients(self, recipie_list=None): return do_something_boring(recipie_list) class IngredientsDescriptor(object): def __init__(self, ingredients_manager): self.ingredients_manager = ingredients_manager def __get__(self, instance, type=None): if instance is not None: raise AttributeError, "Access via %s instances is not allowed" % type.__name__ return self.ingredients_manager Then, "at another time, wanting to know what all the ingredients would be to make cookies, cake and bread" you would call: RecipieClass.objects.get_ingrendients(['cookies','cake','bread']) Both Django and Google Apps Engine API use similar concepts and you can learn much more interesting looking in their source code. Regards, -- Ivan -- http://mail.python.org/mailman/listinfo/python-list