are docstrings for variables a bad idea?

J

jelle

That's basically the idea...
Often i find myself annotating what variables actually stand for, so to
refer back to the code in half a year or so.

# check if ID's or coords
self.pointIDs = ptIDs
self.coords = [tuple(RS.PointCoordinates(i)) for i in ptIDs]

# map ids/coords and coords/ids
self.pointID_2_Coord, self.coord_2_pointID = {}, {}
for id, coord in zip(self.pointIDs,self.coords):

self.coord_2_pointID[coord] = id
self.pointID_2_Coord[id] = coord

# initiate kdtree
self.kdTREE = kdtree.kdtree(3)
for i in self.coords:
self.kdTREE.addPoint(i)

# break down interfaceCrvID
self.segments = list(RS.ExplodeCurves(interfaceCrvID))

# dictionary with a midpoint for each segment
self.segmentCoords = {}
for i in self.segments:
self.segmentCoords = list(RS.CurveMidPoint(i))

and so on...
Please don't say that naming variables properly suffices for any
skilled programmer... really...

When programming a more complex class, it would be quite helpful that
these annotations would pop-up as a docstring.
Often I find myself referring back to a module containing the class to
read back what data the variable holds exactly. A time consuming
activity that could be seriously sped up by a proper IDE
(I'm on SPE, thanks Stani!)

Would that make sense to anyone?

cheers,

-jelle
 
D

Diez B. Roggisch

jelle said:
That's basically the idea...
Often i find myself annotating what variables actually stand for, so to
refer back to the code in half a year or so.

# check if ID's or coords
self.pointIDs = ptIDs
self.coords = [tuple(RS.PointCoordinates(i)) for i in ptIDs]

You aren't annotating variables - you describe what the next lines are
supposed to do, possibly involving new variables. Nothing new here...

I don't know for sure what you mean by "pop up as doc-string" - I guess you
want them magically merged into the functions doc string, at least inside
your editor? That sure could be done - but I personally don't think that is
too useful. Because you lose context. It might be that a particular comment
only applies inside an if-statement. So at least indention should be
preserved. But then - why not just look at the source...

IMHO commenting the parameters and results of a function is what someone
needs who skims the docs for enlightenment. I don't care _how_ a function
works, but _what_ it does. If I need the former, there is nothing that
works beside looking at the source - of course good comments ease the task
of understanding what's going on.

Diez
 
J

jelle

---I don't know for sure what you mean by "pop up as doc-string" - I
guess you
want them magically merged into the functions doc string, at least
inside
your editor? That sure could be done - but I personally don't think
that is
too useful. Because you lose context.---

point taken. perhaps only variables declared in the __init__ should be
made available as a doc string.

---IMHO commenting the parameters and results of a function is what
someone
needs who skims the docs for enlightenment---

these are two completely different things:

f = instanceSomeClass() -> 'pops up the __init__ doc string in your
IDE'

now, when this class is instanced, i think this could be useful:

f.someComplexMethod -> 'pops up the variable docstring'

I'm all for DRY -dont repeat yourself-, but DHORYEBNPTMTRYCEBPTSWTITDS
-don't have others repeat your efforts by not providing the means to
reuse your code efficiently by providing them sparsely with the
information to do so-

could have some place in complex classes that are often subclassed.
having the right information at the right time to do so would be quite
a help.
be fair: do you perfectly well know how to subclass a class without
(extensively) reading it back?

perhaps a variable doc here and there would make this slightly easier.

-jelle
 
B

bearophileHUGS

Docstrings for variables seems a new interesting idea to me, but I
don't know how much useful it can be. Do you mean something like this?
int(x[, base]) -> integer
........

Can you show me some examples of its possible usefulness?

Bye,
bearophile
 
D

Diez B. Roggisch

jelle said:
---I don't know for sure what you mean by "pop up as doc-string" - I
guess you
want them magically merged into the functions doc string, at least
inside
your editor? That sure could be done - but I personally don't think
that is
too useful. Because you lose context.---

point taken. perhaps only variables declared in the __init__ should be
made available as a doc string.

---IMHO commenting the parameters and results of a function is what
someone
needs who skims the docs for enlightenment---

On a related note: for someone who's goal is more clarity in coding, your
style of quoting is thwarting that efforts.
these are two completely different things:

f = instanceSomeClass() -> 'pops up the __init__ doc string in your
IDE'

now, when this class is instanced, i think this could be useful:

f.someComplexMethod -> 'pops up the variable docstring'

I feared that you meant that - but wasn't sure. This is one of the
often-requested-yet-they-will-never-come features of IDEs for python, as
this would mean that you'd have type-information available on f. Consider
this simple example:

f = someRandomlyInstatiatedObject()

Now what is e.g. f.<C-space> to show?

Additionally, if you typed f.foo yourself, is it foo of Foo, or foo of
FooSubclass, or foo of the totally unrelated Badabum?
I'm all for DRY -dont repeat yourself-, but DHORYEBNPTMTRYCEBPTSWTITDS
-don't have others repeat your efforts by not providing the means to
reuse your code efficiently by providing them sparsely with the
information to do so-

could have some place in complex classes that are often subclassed.
having the right information at the right time to do so would be quite
a help.

This is sort of a tautology and applies to pretty much everything in life :)
be fair: do you perfectly well know how to subclass a class without
(extensively) reading it back?

Sure you have to. but then you read the source.
perhaps a variable doc here and there would make this slightly easier.

I'm still not seeing what you are really after. Python has no variable
declarations, so there is no natural point to put these, as it is e.g. in
JAVA. Gathering inline comments by some heuristics like "the following
statement has a assignment" might be feasible to implement, yet I fail to
see the usefulness for that, at least for methods in general.
The exception from this would be the constructor, as sensible design
usually makes all instance variables known there - so something that
mangles

def __init__(self):
# know where your foo is
self.foo = 'here'

might be of interest. But then - it often enough happens that in some method
after some obscure logic some instance variable gets created.

Don't get me wrong: I'm all in favor of commenting code. But your wish for
semi-automatic doc-generation doesn't appeal to me. Now as I'm not the one
and only one to decide about this, if you come up with a reasonable
proposal how to document variables & how to make this available (in way
more technical terms than just "wouldn't it be nice to have") you might
convince some IDE-authors to adopt I gues.

Diez
 
J

jelle

didn't you just do that ;')

such variables docstrings would help one to speed up understanding an
API, and more importantly, could reduce assumptions you make on what a
variable means.
who's the mother of assumptions again?

i'm not evangalizing at all that each and every variable should be
documented!
but one cannot deny there is a certain degree of entropy in the
understanding of classes you even wrote yourself. so variables
docstrings could be very helpful notes to oneself and others.

imagine you wrote a python script that runs a FEM simlation overnight,
relating drag to speed.

rcar.speed -> 'resulting velocity to rcar.drag'

these little notes could help you not to make the same false assumption
you've overcome a year ago, and are likely to make again.

also in cases (most) where you are not the sole operator on a class,
these little hints can be appreciated.

a variables doctring should never be longer than 2 lines to be any good
likely.
ok.
3

-jelle
 
R

Roy Smith

"jelle said:
When programming a more complex class, it would be quite helpful that
these annotations would pop-up as a docstring.

I'm currently working with a OO database system that lets you attach a doc
string not just to classes, but also to attributes, relationships, pretty
much anything. It's very useful.

That being said, I'm not sure how such a thing would work in Python. In
what I'm used to, the doc strings are attached to the variable declarations
in the class definition, so there's just one copy of the string per class.
Python doesn't work that way. In Python, if I were to write:

class GeographicCoordinate:
def __init__ (self, lat, long):
self.lat = lat "Latitude in degrees (positive North), per WGS84"
self.long = long "Longitude in degrees (positive West), per WGS84"

each *instance* of GeographicCoordinate gets a self.lat and a self.long
created in it, with no relationship between the attributes of one instance
and another. Where would the doc strings go? The only logical place would
be to have one copy per instance, which would be very wasteful.

On the other hand, since strings get interned, maybe it wouldn't be so bad.

On the third hand, I guess the doc strings could get attached to the
class's __slots__, which would immediately lead to more "but that's not
what __slots__ was intended for" arguments :)
 
J

jelle

Hi Diez,

please take note, this suggestion does not nessecarily apply to
programmers such as you & myself of course for whom any python code is
as transparant as the API's we write ;')


----
I feared that you meant that - but wasn't sure. This is one of the
often-requested-yet-they-will-never-come features of IDEs for python,
as
this would mean that you'd have type-information available on f.
Consider
this simple example:

f = someRandomlyInstatiatedObject()

Now what is e.g. f.<C-space> to show?
----

why is this ambigious at all?
am i seriously overlooking something?

class jelle:
def __init__(self):
'''
we've been having this for a while, just the helpful
constructor docstring
'''
'''relates drag to speed'''
self.terribleNamedMethod = 'of a programmer i will not
disclose'

j = jelle() shows the proper docstring al'right....
 
M

Michele Simionato

Notice that class attributes can already be annoted (properties have a
docstring). BTW
in Python 2.5 you have a convenient way to define readonly attributes
(for instance
constants) and give them a docstring. Here is an example:

class C(object):
@property
def pi(self):
'pi is 3.14159'
return 3.14159

c = C()

print c.pi

help(C.pi) # gives you the docstring


Michele Simionato
 
J

jelle

----
class GeographicCoordinate:
def __init__ (self, lat, long):
self.lat = lat "Latitude in degrees (positive North), per
WGS84"
self.long = long "Longitude in degrees (positive West), per
WGS84"
----

Thanks for your example Roy, that illustrates well what I'm after:
self.lat = lat "ellipsoid reference: WGS84\nGRS 80 no longer supported"

It does exactly what its intended to do: i had no clue what the World
Geodetic System and would have asserted my input with a GRS80_2_WGS84
function

Little notes to avoid major mistakes.

class landClimateOrbiter(NASA):

self.speed = self.unit * x

Just imagine 'feet' would have popped up when typing self.unit
 
J

jelle

Hi Michele,

Thanks for pointing that out, cool!

I would argue -even- that is too much programming effort.
Like method docstring, variables docstrings should be effortless to
write.
 
D

Diez B. Roggisch

jelle said:
why is this ambigious at all?
am i seriously overlooking something?


Yes. A full example is this:

import random

class A:
"""I'm A
"""
pass

class B:
""" I'm B
"""
pass

def factory():
if random.random() >= .5:
return A()
return B()


o = factory()


Now what is the IDE to show at o for the docstring?


The point is: pythons dynamic nature allows for _runtime_ checks of this
only. Now the special-case of classes can be worked around with a static
analyzer to some extent - because ususally, import statements are easy
enough to spot and resolve statically.

But using __import__ even that can be obfuscated. Now I'm not saying that
this should suppress all efforts to have IDEs more supportive. Yet a class
is a declaration, as is a method - can be parsed easily. But e.g. setting
an instance variable by means of setattr(self, name, value) instead of
self.<name> = value is perfectly legal, often wanted and totally opaque to
any IDE trying to give support.

Diez
 
Z

Ziga Seilnacht

jelle said:
Hi Michele,

Thanks for pointing that out, cool!

I would argue -even- that is too much programming effort.
Like method docstring, variables docstrings should be effortless to
write.

I don't know what exactly do you mean with variable docstrings, but
if you just want to add docstrings to instance's data attributes, you
can use something like this:

"""
This module is useful for documenting data attributes. Example:
.... foo = attr('a common attribute in examples')
.... bar = attr('this one has a name for nicer errors', 'bar')
.... baz = attr('and this one has a default value', default=1)
.... def __init__(self, foo=None, bar=None, baz=None):
.... if foo is not None:
.... self.foo = foo
.... if bar is not None:
.... self.bar = bar
.... if baz is not None:
.... self.baz = baz
....Traceback (most recent call last):
...
AttributeError: 'C' object has no attribute ''Traceback (most recent call last):
...
AttributeError: 'C' object has no attribute 'bar'3

"""

class Marker(object):

def __init__(self, representation):
self.representation = representation

def __repr__(self):
return self.representation


_NoDefault = Marker('NoDefault')


class attr(object):

def __init__(self, doc='', name='', default=_NoDefault):
self.__doc__ = doc
self.name = name
self.default = default

def __repr__(self):
s = "attr(doc=%r, name=%r, default=%r)"
return s % (self.__doc__, self.name, self.default)

def __get__(self, obj, objtype):
if obj is None:
return self
if self.default is _NoDefault:
msg = "%r object has no attribute %r"
raise AttributeError(msg % (objtype.__name__, self.name))
return self.default


if __name__ == '__main__':
import doctest
doctest.testmod()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top