How to write meaningful docstrings? [closed] - python

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 21 days ago.
Improve this question
What, in Your opinion is a meaningful docstring? What do You expect to be described there?
For example, consider this Python class's __init__:
def __init__(self, name, value, displayName=None, matchingRule="strict"):
"""
name - field name
value - field value
displayName - nice display name, if empty will be set to field name
matchingRule - I have no idea what this does, set to strict by default
"""
Do you find this meaningful? Post Your good/bad examples for all to know (and a general answer so it can be accepted).

I agree with "Anything that you can't tell from the method's signature". It might also mean to explain what a method/function returns.
You might also want to use Sphinx (and reStructuredText syntax) for documentation purposes inside your docstrings. That way you can include this in your documentation easily. For an example check out e.g. repoze.bfg which uses this extensively (example file, documentation example).
Another thing one can put in docstrings is also doctests. This might make sense esp. for module or class docstrings as you can also show that way how to use it and have this testable at the same time.

From PEP 8:
Conventions for writing good documentation strings (a.k.a.
"docstrings") are immortalized in PEP 257.
Write docstrings for all public modules, functions, classes, and methods. Docstrings are not necessary for non-public methods, but you
should have a comment that describes what the method does. This
comment should appear after the "def" line.
PEP 257 describes good docstring conventions. Note that most importantly, the """ that ends a multiline docstring should be on a
line by itself, and preferably preceded by a blank line.
For one liner docstrings, it's okay to keep the closing """ on the same line.

Check out numpy's docstrings for good examples (e.g. http://github.com/numpy/numpy/blob/master/numpy/core/numeric.py).
The docstrings are split into several sections and look like this:
Compute the sum of the elements of a list.
Parameters
----------
foo: sequence of ints
The list of integers to sum up.
Returns
-------
res: int
sum of elements of foo
See also
--------
cumsum: compute cumulative sum of elemenents

What should go there:
Anything that you can't tell from the method's signature. In this case the only bit useful is: displayName - if empty will be set to field name.

The most striking things I can think of to include in a docstring are the things that aren't obvious. Usually this includes type information, or capability requirements - eg. "Requires a file-like object". In some cases this will be evident from the signature, not so in other cases.
Another useful thing you can put in to your docstrings is a doctest.

I like to use the documentation to describe in as much detail as possible what the function does, especially the behavior at corner cases (a.k.a. edge cases). Ideally, a programmer using the function should never have to look at the source code - in practice, that means that whenever another programmer does have to look at source code to figure out some detail of how the function works, that detail probably should have been mentioned in the documentation. As Freddy said, anything that doesn't add any detail to the method's signature probably shouldn't be in a documentation string.

Generally purpose of adding adding doc string in starting of function is to describe function, what it does, what it would return, and description about parameters. You can add implementation details if required. Even you can add details about author who wrote the code for future developer.

Related

annotation for the documentation differs from the annotation for the type checking [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 12 months ago.
Improve this question
I need some help how to write the type hints, and it is not purely technical.
As an example, imagine a get_state() function returning the current state as a string.
The documentation states the initialize() must be called first and the result of get_state() is undefined prior to initialization. Actually it returns None when uninitialized, but that is an implementation detail.
The annotation could be:
get_state() -> str which is correct assuming a proper usage. I find it helpful from the developer's point of view, but mypy complains because it is clear that the return value could be also None.
get_state() -> str|None which matches the reality the most, but may change in the future and it introduces mypy warnings everywhere the return value is used and is obviously expected to be a string there.
get_state() -> Any which exactly matches the documented API, but is useless.
So, who is the main recipient of the information in the annotation? Is it the developer getting additional information when reading the code? Or is it the type checker tool like the mypy that tries to find possible problems?
Probably str|None is what you want.
In my view, type annotations in Python try to reap some of the same benefits that static type systems bring to languages that have them. Good examples of languages with strong static type systems are Haskell and Rust. In such languages type annotations can never overpromise, like would happen with get_state() -> str. So that possibility is ruled out. get_state() -> str|None happens to be what the code is capable of supporting, so that is one option, and the documentation should probably then reflect that as well. If the developers think that this return type is likely to change or be different on different systems then it could be reasonable to go for a type like Any, but that would also have implications for how this function should be used. If all you know about this function is that it could return Any(thing) then what exactly can you do with this value? You could test whether it is a string and then use it as a string, but is that the way recommended in the documentation? If yes then the Any type is reasonable, if not then not.
These annotations are mostly for the developer as they don't affect runtime. That said, the type checker is also there to make your life easier. So if any of these are making it harder for you don't have to use them...
And more practically, can you return an empty sting ('') instead of None?

hasattr is called a method, but it looks like a function [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
In Python a function takes arguments and optionally returns information.
functionname(param1, param2)
returnvalue = functionname(param1, param2)
A method in Python is called on an object. So, first specify the object, then a dot and then the method you want to execute
objectname.methodname(param, param)
Like Python rfind and many many other methods.
hasattr
hasattr is used like this:
hasattr(my_object, method_to_test_for_existence)
This is clearly a function according to the definition.
Why are some sites calling hasattr a method instead of a function?
TestPassport with their first test question. (This one worries me since I'm preparing for the PCAP exam :-) )
GeeksForGeeks with the title "Python hasattr() method" (while in their first line they say: 'Python hasattr() function is an inbuilt utility function')
Python's official documentation defines it like this (thank you to #Kelly Bundy here!):
function
A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body. See also parameter, method, and the Function definitions section
method
A function which is defined inside a class body. If called as an attribute of an instance of that class, the method will get the instance object as its first argument (which is usually called self). See function and nested scope.
A square is a rectangle, but not all rectangles are squares. The way I interpret the world, a method is a function, but not all functions are methods. What makes a method unique is that it is a special type of function which also is associated with a class and has access to class member variables.
Your assessment is correct.
The official Python documentation also has hasattr() in its list of "Built-in Functions" (which are technically actually built-in "callables", since some are callable class objects, not standard functions; thanks #chepner). hasattr() is only a function, not also a method.
I believe #khelwood is correct:
It turns out that people sometimes say method when they mean function.
People frequently misuses terms, and people are simply erroneously interchanging the terms function and method even though they are subtly different, as a method is a special type of function.
Misusing terms and incorrectly exchanging one for another happens in programming all the time. It seems to me about 90% of programmers misuse, confuse, and inter-change the words "setup" (the noun) and "set up" (the verb). It also happens in plain old English all the time! It seems to me that about 70% of Americans misuse "good" and "well", erroneously interchanging them, as well as "fewer" and "less" ("I have less pancakes than you" is grammatically incorrect--the word fewer should have been used), "there's" vs "there are" (I find myself frequently misusing "there's" in place of "there are"), etc.
Anyway, if you see someone misusing the term "method" when they mean "function", just interpret it correctly in your head and know you are correct :).
Here's an article I found which I think is pretty good. TutorialsPoint isn't always correct, but this article seems to be correct and well-written: TutorialsPoint.com: Difference between Method and Function in Python. (Then again, it's also possible they plagiarized that article from an answer on Stack Overflow, as I've seen them do that before without even giving attribution. Case in point: this TutorialsPoint.com article appears to be directly plagiarized from this Stack Overflow answer. I emailed TutorialsPoint on 23 Oct. 2020, and they replied, "Sure Gabriel, we will look into it.", on 25 Oct. 2020.)
See also:
What's the difference between a method and a function? (and my answer to this question)
TutorialsPoint.com: Difference between Method and Function in Python

Best practice for the order of function arguments in Python [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I often write functions that take one argument with data to be manipulated, and one or more additional arguments with specifications for the manipulation. If the "specification" parameters are optional, it makes sense to place them after the obligatory data argument:
sort(data, key=..., reverse=True)
But suppose both arguments (or several of them) are obligatory? The functions of the re module place the regexp (the manipulation) before the string (the data to be manipulated). Optional arguments still come last, of course.
re.search(r"[regexp]+", text, flags=re.I)
So here's the question: Putting optional arguments aside, are there any clear conventions (official PEP or established common practice) for how to order obligatory arguments based on their function/purpose? Back when I was first learning Python, I remember reading some claim to the effect that one of Python's advantages is that it has clear conventions, inter alia on this particular thing. But I am unable to retrieve any such information now.
In case it is not clear: I am kindly asking for pointers to established conventions or standards, not for advice on which order is "best."
This is one hell of a good question and I'm already excited to see other answers. I've never come across any conventions about functions arguments in Python except in PEP 8 where it states that:
Always use self for the first argument to instance methods.
Always use cls for the first argument to class methods.
If a function argument's name clashes with a reserved keyword, it is
generally better to append a single trailing underscore rather than
use an abbreviation or spelling corruption. Thus class_ is better than
clss. (Perhaps better is to avoid such clashes by using a synonym.)
In my opinion, functions parameter should always be in order of importance. I know importance is subjective but you generally can determine which of the parameters is the most important to your function. Since StackOverflow is not about opinion take this with a grain of salt.
So putting aside opinions, I think your question is relevant but sometimes questions leads to other discussions. If you have numerous parameters, your function is probably doing too much stuff. According to a lot of ressources, you should try to use only one parameter and avoid using more than three where the latter is considered as the worst case scenario. So, most of the time ordering parameters won't impact readability that much if you keep that in mind.
I try to order parameters to help code readability (literate programming).
ex:
system.add(user, user_database) # add a user to a database
system.add(user_database, user) # add a database to a user(?)
This usually coincide with #scharette's opinion, the "most important" parameter is the object for which the function was created for. But as (he) stated it's subjective, it could be argued the database is the most important object in a database system library.
Reading code should reveal intent on first read; reading a set of function definitions should reveal what they do.

If my python class name has an acronym, should I keep it upper case, or only the first letter? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I have a class named SSLXMLRPCServer. Should it be that or SslXmlRpcServer?
This is a matter of personal preference, but I find the second format much easier to read. The fact that your first format has a typo in it (PRC instead or RPC) suggests that I am not the only one.
It should be SSLXMLRPCServer, to match the standard library classes like SimpleXMLRPCServer, CGIXMLRPCRequestHandler, etc.
Adopting a naming convention that differs from equivalents in the standard library is only going to confuse people.
The problem with uppercase acronyms in CamelCase names is that the word following the acronym looks like a part of it, since it begins with a capital letter. Also, when you have several in a row as in your example, it is not clear where each begins. For this reason, I would probably use your second choice.
The PEP-8 mentions nothing about acronyms. You would be safest to keep the acronyms uppercased (it's what I see most).
I normally uppercase acronyms. Twisted and a few other libraries do this as well.
As stated already, PEP-8 says to use upper-case for acronym. Now, python zen also says "readability counts" (and for me the zen has priority over the PEP :-).
My opinion in such unclear situation is to take into account the standard in the programming context, not just the language. For example, some xml-http-query class should be written XMLHttpQuery in a servlet context (w.r.t XMLHttpRequest).
I don't know your context, but it seems XMLRPCServer exists and you want to attach ssl to it. So you could choose something like:
SSL_XMLRPCServer
It would emphasized the XMLRPCServer -without changing it-.
Also, you'd stay close to PEP-8 and follow the zen :-)
My 2 cents
Note: if XMLRPCServer is not strongly related to your class and is really a standard in the domain, then you need to choose another name, as to not be confusing.
I had this problemlots of time . I uppercase Acronym but I doesn't like it because when you chain them (as in your example) it doesn't feel right. However I think the best things to do is to make a choice and stick to hit, so at least don't you know when you need to reference something how it's written without having to check (which is one of the benefit of coding standard)
How about SSL_XML_RPC_Server for acronymity and readability?
It's what I often do when I want to avoid camel-case for some reason.

Function overloading in Python: Missing [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 13 years ago.
As function overloading says:
Function overloading is absent in Python.
As far as I feel this a big handicap since its also an object-oriented (OO) language. Initially I found that unable to differentiate between the argument types was difficult, but the dynamic nature of Python made it easy (e.g. list, tuples, strings are much similar).
However, counting the number of arguments passed and then doing the job is like an overkill.
Now, unless you're trying to write C++ code using Python syntax, what would you need overloading for?
I think it's exactly opposite. Overloading is only necessary to make strongly-typed languages act more like Python. In Python you have keyword argument, and you have *args and **kwargs.
See for example: What is a clean, Pythonic way to have multiple constructors in Python?
As unwind noted, keyword arguments with default values can go a long way.
I'll also state that in my opinion, it goes against the spirit of Python to worry a lot about what types are passed into methods. In Python, I think it's more accepted to use duck typing -- asking what an object can do, rather than what it is.
Thus, if your method may accept a string or a tuple, you might do something like this:
def print_names(names):
"""Takes a space-delimited string or an iterable"""
try:
for name in names.split(): # string case
print name
except AttributeError:
for name in names:
print name
Then you could do either of these:
print_names("Ryan Billy")
print_names(("Ryan", "Billy"))
Although an API like that sometimes indicates a design problem.
You don't need function overloading, as you have the *args and **kwargs arguments.
The fact is that function overloading is based on the idea that passing different types you will execute different code. If you have a dynamically typed language like Python, you should not distinguish by type, but you should deal with interfaces and their compliance with the code you write.
For example, if you have code that can handle either an integer, or a list of integers, you can try iterating on it and if you are not able to, then you assume it's an integer and go forward. Of course it could be a float, but as far as the behavior is concerned, if a float and an int appear to be the same, then they can be interchanged.
Oftentimes you see the suggestion use use keyword arguments, with default values, instead. Look into that.
You can pass a mutable container datatype into a function, and it can contain anything you want.
If you need a different functionality, name the functions differently, or if you need the same interface, just write an interface function (or method) that calls the functions appropriately based on the data received.
It took a while to me to get adjusted to this coming from Java, but it really isn't a "big handicap".

Categories