On Sep 26, 12:25 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Tue, 25 Sep 2007 22:41:31 -0300,KenKuhlman<kskuhl...@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__