Best way to do attribute docstrings?

Ken Kuhlman kskuhlman at gmail.com
Wed Sep 26 23:26:32 EDT 2007


On Sep 26, 12:25 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
wrote:
> En Tue, 25 Sep 2007 22:41:31 -0300,KenKuhlman<kskuhl... at gmail.com>
> escribi?:
>
> > Replying to myself in case someone finds this interesting.
>
> > Anyway, I took another shot at this with a little fresher mind, and it
> > was quickly obvious that I was trying to force attributes to behave
> > more like classes.  It was a small step from there to creating a
> > factory function to return instances of the appropriate class.  I'm
> > much happier with the result than either of the two previously posted
> > kludges.
>
> Still there is something I don't understand on your design. You appear to
> be always concerned about *class* attributes. *Instance* attributes are
> far more comon, and usually they change their value many times.
>
...
> Gabriel Genellina


I've only cared about class attributes to this point because my needs
have been simple.  They may not always be, however, so I'll take a
shot at your challenge (below).   I've basically just added a base
class that defines __setattr__ to the mix.

Thanks for the replies!
-Ken


# A factory function for generating attributes that can be annotated.
def attr(value, doc=None):
    base = type(value)
    if base == bool:
        # bool class can't be used as a base, so we make one that can.
        class MyBool(int):
            def __str__(self):
                return str(bool(self))
            __repr__ = __str__
        base = MyBool

    class FancyAttr(base):
        pass

    fa = FancyAttr(value)
    fa.__doc__ = doc
    return fa

class AnnotatedAttrsBase(object):
    _sticky_docs = True #False
    def __setattr__(self, name, value):
        """ Make sure attributes are fancy, maintaining docs if
they're sticky. """
        if type(value).__name__ != 'FancyAttr':
            doc = None
            if self._sticky_docs and hasattr(self, name):
                doc = self.__dict__[name].__doc__
            self.__dict__[name] = attr(value, doc)
        else:
            self.__dict__[name] = value

class Animal(AnnotatedAttrsBase):
    can_fly = attr(value = False,
                   doc = "no Animal can fly unless explicitly noted")
    lives = attr(value = 1,
                 doc = "most Animals have a single life")
    def __init__(self, color, legs, favorite_food):
        self.color = attr(color, "every animal has a color")
        self.legs = attr(legs, "most animals have legs")
        self.favorite_food = favorite_food

class Mammal(Animal):
    pass

class Cat(Mammal):
    def __init__(self, color):
        Mammal.__init__(self, color=color, legs=4,
favorite_food='mice')
        self.lives = attr(value = 7,
                          doc = "a cat starts with 7 lives")

class Mouse(Mammal):
    def __init__(self, color, personality):
        Mammal.__init__(self, color=color, legs=4,
favorite_food='cheese')
        self.personality = personality

class Bird(Animal):
    can_fly = True
    _sticky_docs = False
    def __init__(self, color):
        Animal.__init__(self, color=color, legs=2,
favorite_food='seed')

tweety = Bird('yellow')
tweety.lives = 42
sylvester = Cat('black')
tom = Cat('blue')
jerry = Mouse('brown', 'nice')
itchy = Mouse('blue', 'sadist')
scratchy = Cat('black')
scratchy.lives = attr(7**7, "or so...")

print scratchy.color, scratchy.color.__doc__
print scratchy.lives, scratchy.lives.__doc__
print tweety.legs, tweety.legs.__doc__
print tweety.lives, tweety.lives.__doc__




More information about the Python-list mailing list