473,394 Members | 1,693 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Best way to do attribute docstrings?


What's the best method for annotating attributes with a docstring?
I'm looking to be able to introspect my class & get the comments back
out.

The technique I'm using is a little hoaky, but works.. basically I
create subclasses of the builtin types that I want to be able to use &
then instantiate them in my attribute assignments. This gives me an
object that I can tweak the __doc__ attribute on. An example of what
my code looks like is included below.

I saw that PEP 224 [1] was trying to meet this need, but got rejected
because the proposed syntax wasn't clear enough.

Thanks!
-Ken

[1] http://www.python.org/dev/peps/pep-0224/
attr_doc.py::

# Subclass str so we can modify instance's attributes (like __doc__)
class _(str): pass

# Boolean gave me extra fits that I don't understand, but this
technique works
class MyBool(int):
def __str__(self):
return `self.__int__() 0`
def __repr__(self):
return self.__str__()

def bool_func(val):
def blah():
return MyBool(val)
return blah
true = bool_func(True)
false = bool_func(False)
class Animal(object):
four_legs = true()
four_legs.__doc__ = "Animal has four legs"

favorite_food = _('cheese')
favorite_food.__doc__ = "Animal's favorite food"

has_fur = true()
has_fur.__doc__ = "Animal has fur"

print Animal.four_legs.__doc__, '::', Animal.four_legs
print Animal.favorite_food.__doc__, '::', Animal.favorite_food
print Animal.has_fur.__doc__, '::', Animal.has_fur

------
This gives the expected results:

Animal has four legs :: True
Animal's favorite food :: cheese
Animal has fur :: True

Sep 7 '07 #1
5 2047
En Fri, 07 Sep 2007 17:06:07 -0300, Ken Kuhlman <ks*******@gmail.com>
escribi�:
What's the best method for annotating attributes with a docstring?
I'm looking to be able to introspect my class & get the comments back
out.
I don't know which is the *best* method. Perhaps you might use properties
instead. Or some kind of convention, like
four_legs__doc__ = "Animal has four legs"
to be the docstring associate to `four_legs` attribute.
The technique I'm using is a little hoaky, but works.. basically I
create subclasses of the builtin types that I want to be able to use &
then instantiate them in my attribute assignments. This gives me an
object that I can tweak the __doc__ attribute on. An example of what
my code looks like is included below.
I don't like subclassing builtins, it doesn't work in general. _("Hello")
+ _(" world!") is a plain str object, not your derived class.
What about instance attributes? All your examples show class attributes.
Your docstring appears to be attached to the attribute "value", but it
should be attached to the attribute definition, or be a class attribute,
or something like that, shared between all instances and somewhat
permanent. Else, reassigning the attribute will lose the docstring.
# Boolean gave me extra fits that I don't understand, but this
technique works
class MyBool(int):
def __str__(self):
return `self.__int__() 0`
def __repr__(self):
return self.__str__()
Let Python do the boolean conversion: -1 is a true value, but MyBool(-1)
would say False.
I don't understand exactly why do you want this class, but I'd write it
this way:

class MyBool(int):
def __str__(self):
return str(bool(self))
__repr__ = __str__
def bool_func(val):
def blah():
return MyBool(val)
return blah
true = bool_func(True)
false = bool_func(False)
And why do you need such functions?

--
Gabriel Genellina

Sep 8 '07 #2

Thanks for the response! It was just the kick I needed to realize
that I was letting my frustration get the best of me and that I was
going down a dead-end. I blame the fact that I was coding on little
sleep :-)

I went with the solution of giving a naming convention to the
docstrings and relying on that for the introspection -- that's a lot
less of a kludge than what I was attempting.

I still think it would be great if you could do something like:
@doc('Animal has four legs')
four_legs = True

IMHO, that syntax is nice (which was the objection to PEP 224), but
I'm not going to try to propose another PEP over it. My itch is
scratched for now -- if the naming convention hack gets under my skin
eventually I'll try going down a source parsing route next.

Thanks again for the help!
-Ken

PS: I hope it's OK that I ignored your questions -- my initial
solution was just too hideous to be scrutinized too closely.

Sep 11 '07 #3
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.
# 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 Animal(object):
four_legs = attr(value = True, doc = "Animal has four legs")
favorite_food = attr('cheese', doc = "Animal's favorite food")
has_fur = attr(False)
has_fur.__doc__ "Animal has fur"

print Animal.four_legs.__doc__, '::', Animal.four_legs
print Animal.favorite_food.__doc__, '::', Animal.favorite_food
print Animal.has_fur.__doc__, '::', Animal.has_fur
Sep 26 '07 #4
En Tue, 25 Sep 2007 22:41:31 -0300, Ken Kuhlman <ks*******@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.
class Animal(object):
four_legs = attr(value = True, doc = "Animal has four legs")
favorite_food = attr('cheese', doc = "Animal's favorite food")
has_fur = attr(False)
has_fur.__doc__ "Animal has fur"
As an example, how would you annotate attributes on a hierarchy like this?

class Animal(object):
can_fly = False # no Animal can fly unless explicitely noted
lives = 1 # most Animals have a single life
def __init__(self, color, legs, favorite_food):
self.color = color
self.legs = 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 = 7 # 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
def __init__(self, color):
Animal.__init__(self, color=color, legs=2, favorite_food='seed')

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

print tweety.legs
print scratchy.color
print scratchy.lives

--
Gabriel Genellina

Sep 26 '07 #5
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__

Sep 27 '07 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Sridhar R | last post by:
When writing a python library, we can use docstrings for methods and functions that are part of API. But what about comments for non-API objects or python application code? For applications,...
2
by: Steven Bethard | last post by:
I have two classes that implement the same interface, e.g. something like: class C(object): def foo(self): """Foo things""" ... def bar(self): """Bar things""" ... def baz(self):
6
by: Kamilche | last post by:
I have a large project that is getting complex, and I would like to print the docstrings without importing the modules. The only Python utility I could find references is apparently defunct and...
9
by: Scott Huey | last post by:
I am working on a Python module and I would like to prepare some API documentaiton. I managed to find epydoc after some searching online. Is there a standard way to document the API for Python...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.