How To Use Comments Effectively In Python | by Emmett Boudreau | Towards Data Science

There are many tools that a software engineer or data scientist might use in order to provide more expression to their code. There are many reasons that one might want to do this. For example, comments can be a valuable asset in a step-by-step process that needs to be taught. Comments can also provide valuable information that could be essential to working with certain code.
I think back to one example where I was having to dig through some Julia code because there was no documentation for it. I could not figure out how the input for something was meant to be structured, but then I spotted some odd comment stored off to the side that explained the data-structure exactly how I needed for it to be presented and it was off to the races with my code. While this most definitely was not the best application of comments, it did firmly establish just how vital comments can be to illustrating some points. We cannot expect documentation to carry all of the internal information that a developer might want to know from the original programmer, and this is where comments certainly come in handy.
However, the reason I wanted to talk a bit about using comments is that although they are simple, there is actually an art to using them. That being said, I find it very common to find some rather horrid commenting in newer programmer’s code. Much too often, there are comments that are either contradictory, or directly explanatory... For instance, I do not need a comment telling me that you are doing this arithmetic:
# divide x by 5new = x / 5
If there is any comment for this, it should be above all of the arithmetic, and simply be a formula, for instance:
# z = 3 * 2 + x / 5
In this particular case, however, this still does not make a lot of sense — as there is only one independent variable inside of this expression. There are so many right places to comment, but as a result there are also so many wrong places and things to comment. So without further ado, I would like to offer some personal tips on commenting code effectively, as well as the Python Programming language’s PEP8 convention for commenting one’s code.
First and foremost, PEP8 points out that code needs to stay up-to-date with software. As the code around a given set of comments changes, those comments should be rewritten as well. Comments that do not correctly apply to the code given are worse than having no comments at all. PEP8 also states that comments should be in complete sentences. This is of course with proper grammar and punctuation, such as beginning a sentence with a capital and ending it with a period.
# This would be a proper comment.#this one isn't
There is one exception to this, of course, if we have an existing alias, we should obey the case of that alias in code, such as this example:
# g is Jimmy's heightg = jimmys_height
Not
# G is Jimmy's heightg = jimmys_height
You should use two spaces after a sentence-ending period in multi- sentence comments, except after the final sentence. Of course, these comments should also be readable, and easy to understand. Another weird PEP8 convention is that comments should be in English ... “ Unless you are 120% percent certain that only those who speak your language will view the code” ... (direct quote.) I found this interesting, as I have seen many comments in Spanish, or other languages in the past in some pretty popular Python software.
One more thing, PEP8 says that in-line comments should be used very rarely. To be clear, an in-line comment is simply a comment that follows code.
First and foremost, I want to say that if there is one negative type of comment I would rather see be white-space, it is the
redundant comment.
Comments can be over-used, and this is definitely not something you want to do. Doubling your lines because you are explaining everything you are doing just is not a good coding practice. Do not be this engineer:
# Multiply z and x to get b.b = z * x# Add five to bb += 5# Multiply slope by x and add b:y = m * x + b
We can see what you are doing! This does not need to be commented, and just by staring at this example can you tell that the comments make the code actually harder to read — not easier? A better example of this section would be to label the entire code below it by what this arithmetic actually does, rather than the operations it takes to get there.
# Calculate the line.b = z * xb += 5y = m * x + b
Another thing, adding a space after your pounds is also a convention among programmers. This is definitely a good rule to follow:
# Comment this.#Not this.
I see this as similar to crowding operators next to data, it just makes things hard to read. Another thing is to understand where comments actually belong when describing a phrase. Consider the line phrase from before. We do not want to put an in-line comment anywhere into this, and especially not after it!
# This is correct.b = z * xb += 5    # This is not correct.y = m * x + b# Please do not do this.
You can use comments very effectively to describe the goal of regions of your functions — rather than describing individual lines. While sometimes these certainly are a great idea, consider the following code from my OddFrames.jl package:
function OddFrame(file_path::String)# Create labels/columns from file.extensions = Dict("csv" => read_csv)extension = split(file_path, '.')[2]labels, columns = extensions[extension](file_path)length_check(columns)name_check(labels)types, columns = read_types(columns)# Get our coldata.coldata = generate_coldata(columns, types)# dead function."""dox"""head(x::Int64) = _head(labels, columns, coldata, x)head() = _head(labels, columns, coldata, 5)# drop function.drop(x) = _drop(x, columns)drop(x::Symbol) = _drop(x, labels, columns, coldata)drop(x::String) = _drop(Symbol(x), labels, columns, coldata)# dropna function.dropna() = _dropna(columns)dtype(x::Symbol) = typeof(coldata[findall(x->x == x,labels)[1]][1])# dtype function.dtype(x::Symbol, y::Type) = _dtype(columns[findall(x->x == x,labels)[1]], y)# Create the type.self = new(labels, columns, coldata, head, drop, dropna, dtype);select!(self)return(self);end
The comments are for a Julia package, but really these two should not have much difference when it comes to commenting. In this example, I am using the comments to explain the data I am creating — which is then all comprised in our types. I am describing the output that I am desiring, and you can let the code explain how I get there. I think this is a great way to use comments, as it makes it a lot less challenging to find out what specific areas of the function might be dedicated to.
Honestly, comments are a whole subject matter that I think should be focused a bit more on in terms of education. This is because they are very powerful, but only when used correctly. Of course, a lot of this comes down to what the programmer personally feels the need to comment, which is very subjective. There really is no guide on what to comment and what not to comment.
However, using some of this advice in order to avoid redundancy and look at things from a much more generalized perspective will certainly go a long way towards making your comments more valuable than they might have been in the past. I think we can all constantly improve on this, I know I certainly do not always write comments, and when I do they might be quite vague and not very comprehensive. In a lot of ways, I feel like good code should not need comments. If your code is great, then it should be readable just like reading English or what have you. However, that being said, I still do find a significant benefit to comments when used well, and I can certainly see how they can be effective in certain ways. I hope this little overview of some mishaps that we have all done probably a million times, especially when it comes to the PEP8 side of things, was helpful in making our future code look better and be more comprehensible with accurate, non-redundant comments. Thank you for reading my article.