What PEP 8 guidelines do you ignore, and which ones do you stick to?
Solution 1
The "79 characters per line" part is nonsense. Their very own example shows how unreadable code becomes when doing this:
class Rectangle(Blob):
def __init__(self, width, height,
color='black', emphasis=None, highlight=0):
if width == 0 and height == 0 and \
color == 'red' and emphasis == 'strong' or \
highlight > 100:
raise ValueError("sorry, you lose")
if width == 0 and height == 0 and (color == 'red' or
emphasis is None):
raise ValueError("I don't think so -- values are %s, %s" %
(width, height))
Blob.__init__(self, width, height,
color, emphasis, highlight)
It's like try-
ing to read
a news arti-
cle written
like this.
80-column terminals havn't been a serious development environment for over a decade. When I do need to edit from a crippled 80x25 environment in a pinch, editor wrapping is a minor inconvenience; I'm not going to maim my code during normal development just to avoid that.
120 column wrapping is perfectly sensible for modern development, and I have no problem with 140. This guideline is obsolete and following it results in ugly, hard-to-read code.
Solution 2
PEP8 says to avoid "More than one space around an assignment (or other) operator to align it with another" and "never use more than one space" around math operators, but I don't follow this.
I often add "extraneous whitespace" when neighboring lines are related or very similar, but not quite the same:
search_start = (f - f_1/3) * n/fs
search_stop = (f + f_1/3) * n/fs
b_lpf, a_lpf = filter(N, 2*pi*fc, 'low', analog=True)
b_hpf, a_hpf = filter(N, 2*pi*fc, 'high', analog=True)
p[x > 1] = np.cosh(order * np.arccosh( x[x > 1]))
p[x < -1] = (1 - 2 * (order % 2)) * np.cosh(order * np.arccosh(-x[x < -1]))
b0 = (1 + cos(w0))/2
b1 = -(1 + cos(w0))
Similarly, it's annoying that I get code style warnings for arrays of numbers formatted in the readable way that they are normally formatted by the library itself:
a = array([[-0.198, 0.248, -1.17 , -0.629, 1.378],
[-1.315, 0.947, -0.736, -1.388, 0.389],
[ 0.241, -0.98 , 0.535, 0.951, 1.143],
[-0.601, 1.286, -0.947, 0.037, -0.864],
[ 0.178, -0.289, -1.037, -1.453, -0.369]])
This produces a bunch of E201 E202 E222 violations.
PEP8 would rather have it formatted it like this, apparently, because we can't ever have extra whitespace before commas or after brackets, even if it improves readability:
a = array([[-0.198, 0.248, -1.17, -0.629, 1.378],
[-1.315, 0.947, -0.736, -1.388, 0.389],
[0.241, -0.98, 0.535, 0.951, 1.143],
[-0.601, 1.286, -0.947, 0.037, -0.864],
[0.178, -0.289, -1.037, -1.453, -0.369]])
Solution 3
PEP8 says
Note that most importantly, the """ that ends a multiline docstring should be on a line by itself, and preferably preceded by a blank line, e.g.:
"""Return a foobang Optional plotz says to frobnicate the bizbaz first. """
I find this rather bizarre, since it's just "extraneous whitespace" and treats opening quotations differently from closing quotations for no obvious reason.
A rationale is given is in PEP 257:
The BDFL recommends inserting a blank line between the last paragraph in a multi-line docstring and its closing quotes, placing the closing quotes on a line by themselves. This way, Emacs' fill-paragraph command can be used on it.
Emacs, really? Everyone should do weird things to cater to the idiosyncrasies of a particular command in a particular editing tool?
I also think it's weird to put the beginning of the docstring on the same line as the quotes (not required, but recommended), while insisting that the closing quotations be on their own line. I think this is more logical, and should be used for both single line and multi-line docstrings:
def foobang(bizbaz, plotz=None):
"""
Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""
if plotz is not None:
...
Update: The bold part has been removed and now it just says to "place the closing quotes on a line by themselves", and that the "summary line may be on the same line as the opening quotes or on the next line".
Solution 4
Standards are critical and PEP 8 is a very good style guide that I insist on. The only guideline I disagree with is the spacing around mathematical operators. For example PEP8 insists on the following spacings
Without PEP8 With PEP8
----------------------------------------------------------------
y = sqrt(x**2 + y**2) y = sqrt(x ** 2 + y ** 2)
a*x**3 + b*x**2 + c*x + d a * x ** 3 + b * x ** 2 + c * x + d
10**(a*x + b) 10 ** (a * x + b)
F = V/(sqrt(g*h) + epsilon) F = V / (sqrt(g * h) + epsilon)
a*cos(nx/pi) + b*sin(nx/pi) a * cos(nx / pi) + b * sin(nx / pi)
I am trying to conform, but this is the one area where I am struggling. Do anyone else also feel that PEP8 spacing makes mathematics harder to read?
Update:
PEP8 was corrected to recommend the formatting on the left while discouraging the formatting on the right:
Yes:
i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b)
No:
i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b)
Solution 5
I don't agree with this:
- Imports should usually be on separate lines, e.g.:
Yes: import os
import sys
No: import sys, os
I always write simple imports together. I don't see any advantage to writing them all on separate lines: all it does is add bloat to the top of each source file, and turn something concise and easy to type into something that's borderline boilerplate, eg. something that's so verbose it starts to be tempting to copy and paste from other files.
This is instantly readable and understandable:
import sys, os, time, gc, inspect, math, doctest
It's short, easy to skim, and easy to add to. I do use multiple import
statements if there are too many on one line, of course, or if I need a from
import.
I also do generally keep standard library imports separate from imports of my own modules and other libraries, which agrees with the concept of grouping PEP8 recommends.
Related videos on Youtube
tshepang
I do software development for a living and as a hobby. My favorite language is Rust, and I've used Python much in the past. My OS of choice is Debian.
Updated on August 07, 2020Comments
-
tshepang almost 4 years
Over the years, the more Python I write, the more I find myself agreeing with most of the guidelines, though I consistently and intentionally break some for my own reasons.
I'd be curious to know what in PEP 8 (or other PEPs too maybe) people religiously stick to and why, and what people find inconvenient or inadequate.
In my case (and at work in general), there's only a handful of things we deviate from:
Underscore separated lowercase names, I can see the point of it, as it will unfailingly be consistent, but we tend to use lowerCamelCase, even if it will occasionally introduce some inconsistencies (such as partially or mis-capitalized acronyms and following words, which are often down to spur-of-the-moment calls). Mostly because the near totality of the APIs we routinely use use camelCase (some upper, some lower), and because for some reason I find it easier to read, and tend to reserve underscores as separation tokens or prescribed mangling/obscuring.
I still can't get myself to space things out the way the PEP prescribes inside objects. new and init I tend to leave right under the class with no blank lines as I always want to read them right there with the class name and args, methods that contribute to the same scope of functionality in the class (say init, get and set of the same attrib or set of attribs) I only single-space apart, and I like three spaces between classes, and two between methods I wouldn't mentally aggregate in the map of that object. This is, again, purely for the visual impact and readability of the code. I find that very compact contents inside flow control and this kind of spacing between methods and objects consistently leads my eye exactly where I want it to go on re-readings months after the code had been parked. It also responds well to folding in my editors of choice.
Some things instead I stick to, that drive me nuts when I read otherwise written, is tabs instead of spaces (especially when some in-app editors we use don't really have tab replacement functionalities, contributing considerably to pollution in the code base at prototyping stage).
Order of things such as imports, and what imports, globals etc. It really throws me off on files that have large amounts of imports when those are mixed up or out of order.
Whitespaces in statements, especially when people use tabs AND try to align assignment ops across lines with different length in var names (and there seems to be no way to persuade those who do it that an excel looking piece of code is NOT neater ;) ).
And spacing within a control block, particularly when I see apparently random spacing within the same flow control block, and then similar amounts of spacing used within the object for methods. I'm compelled to edit those before I can even start reading the damn thing.
So, those are mine, and the reasoning behind my "violations" of the PEP (some shared, some frowned upon by colleagues). I'd be very curious to read what other Pythonistas do and don't do in those regards.
-
user1066101 over 13 yearsWhy isn't this community wiki?
-
Nick T over 13 years@S.Lott: Wasn't community wiki removed? Dunno.
-
Glenn Maynard over 13 yearsOh, I didn't notice that. Finally, a change on this site that makes sense--I couldn't stand "community wiki" questions, and made a policy of ignoring them. People took it as permission to reverse answers that they didn't agree with, moving the position they wanted to bury into a footnote...
-
intuited over 13 years@S.Lott, @Nick T, @Glenn Maynard: Important Change - Status completed: Users can not mark questions wiki anymore, across the network.
-
Glenn Maynard over 13 yearsPutting aside my personal distaste of community wiki, an observation: although answers to this question are subjective, I don't think it's meaningful to encourage editing each other's answers. These are opinions; it's not meaningful to edit another person's opinion. (I'll note, though, that I don't think these answers are valueless: people are giving their opinion based on their experiences. That's useful--at least when people give their justifications, and don't simply state their disagreement and walk off.)
-
Admin over 13 yearsI would agree with the need for a wikification of the post if the intention was to try and reach a consensus on how to amend the PEP8 document, but that would probably be better suited to old-school, Python centric mailing lists and NG. This being more about my curiosity about inidividual choices and the reasoning behind them, the resulting wiki entry would become a large collection of weasel statements, or an aggregation of quotes that would border on the poll, neither of which I would find as interesting a read :)
-
Will almost 8 yearsNot closing, because the question is intelligent and there are good answers, and I'm sure this will help people.
-
poke almost 8 years@Will Just because a question may be helpful, it does not make the question objective and on-topic. This is directly asking for people’s opinions which is off-topic. Note that closing a question does not mean that it gets deleted.
-
Admin over 13 yearsPersonally I do use pylint and like it. Mostly I was curious about other programmers personal "amendments" to PEP8, and why they feel they need to bend or ignore a particular guideline :)
-
Glenn Maynard over 13 yearsTwo-space indentation is very hard to read in any language. I'm not a stickler for four-space indents--I often use eight, largely out of long habit--but reading anything less is very uncomfortable.
-
Nick T over 13 years79 characters per line lets one fit two pages of code onto a 1680px wide screen fairly easily. That code could also be formatted much better; it's something of a strawman against 79-character lines.
-
Glenn Maynard over 13 years@Nick: I'm not going to massacre my code to accomodate your weird windowing arrangements. This code is copied directly out of the PEP-8 section on wrapping, so it's pointedly absurd to call it a "strawman".
-
Carlos Balderas over 13 yearsOh, ok, I did not get the point, sorry. =)
-
intuited over 13 yearsI was initially really opposed to the 80-character thing, but I find that if you wrap conditional sections like the one in this example in a set of parentheses, and use lisp-style indentation for it, it works out pretty well. If that's still not possible, I take it as a sign that I'm doing too much in one line, and create an intermediate variable assignment or function to handle part of the complexity. I actually forgot that it was possible to escape newlines with backlashes: I never do that.
-
Glenn Maynard over 13 yearsI might agree with this if you have a long list of related assignments; for example, if you're copying a list of enum values from a C header. For small quantities, as is usually the case for local variables, I'd leave out the alignment, though.
-
intuited over 13 yearsYou don't actually need the end-of-line backslashes here: a line can't end within a set of parentheses, so they continue anyway. I agree with you BTW, it seems clearer to put the conditional where it's obvious at a glance.
-
Nick T over 13 yearsJava seems to love 2 spaces, probably because you will always have to indent two levels before you actually start writing any code.
-
Jeet over 13 yearsre: backslashes -- I know ... but for some reason I tend to add them!
-
Glenn Maynard over 13 yearsContinuation backslashes in Python make me feel like I'm reading a big C preprocessor macro. Nobody should have to feel that way...
-
Glenn Maynard over 13 years@Nick: For all the objective reasons I dislike Java, I have a feeling I'd subjectivally hate it a lot less if it wasn't like that.
-
Lie Ryan over 13 yearsJava requires 2 space indentation to be readable because it's an overly verbose language and anything less causes you to run out of horizontal space too soon
-
Tim McNamara over 13 yearsI find it surprising that this has been down-voted.. the question isn't asking for recommendations. It's just asking for how people behave. The only reason to vote downwards on this answer would be if you knew that I was lying.
-
intuited over 13 years@Tim: +1 because I believe you.
-
user1066101 over 13 years"better readability"? Disputable. It's just your preference. Some of us don't find it readable at all. COBOL programmers do it a lot and it doesn't help there, either.
-
Admin about 13 yearsAgreed on. Spacing within certain operations or assignments become unreadable when used across the board, especially when dealing with precedence different from a serie like with mults/divs. I often collapse some of the additions too if it's outside a parenthesis, it just breaks the reading too much for me otherwise.
-
jfs over 12 yearsSubjectively the left column seems to me as a line noise. At first I even thought that you mislabeled the columns due to the benefit of the right one is literally obvious to my eye (except for the last row).
-
tshepang almost 12 yearsIf you change any of those imports, the diff does not look so good.
-
tshepang almost 12 yearsI think it's fair that people downvote if they think you are behaving badly.
-
Glenn Maynard almost 12 years@Tshepang: It looks fine, compared to the mess of having half a page of imports at the top of a file.
-
Tim McNamara almost 12 yearsBut who would think that I'm behaving badly? It's downvoting an answer to question on how people break rules.
-
kitsu.eb almost 12 yearsI agree, but I try only to do this for Standard modules.
import os, sys
is to common to put on two lines. -
kitsu.eb almost 12 yearsThe extra spaces are ugly. I like spaces around [+-=] and none around [*/%]. I would prefer
^
to**
but neither should have surrounding spaces! -
Lyndsy Simon over 11 yearsGenerally speaking, if you've got more than 79 characters on a line, you're doing more than one thing there and should be breaking it up for readability anyhow. Still, properly descriptive names means that sometimes your lines will extend beyond the limit, and that's fine. Practicality beats purity.
-
Glenn Maynard over 11 years@LyndsySimon: No, that's simply not the case. Well-written, perfectly natural and readable code often extends to 110-120 characters.
-
Lyndsy Simon over 11 years@GlennMaynard IMO, two of Python's greatest strengths are readability and consistency. If your lines regularly go to >79 characters, then you're negatively impacting that. There are reasons to do this that outweigh the negatives - like descriptive variable names - but they are the exception, not the rule. Do you have an example of 110-120 chars of code that you feel should be one line?
-
Glenn Maynard over 11 yearsNo, I'm not; my code is perfectly readable. zewt.org/~glenn/wrapping.py For examples of why wrapping to 80 columns is bad, see PEP-8: it does an excellent job demonstrating how its own advice is wrong, showing how much less readable code is when it's wrapped unnaturally.
-
endolith about 11 years"If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgement; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator." So I think your examples are invalid. These are good according to PEP8:
x = x*2 - 1
,hypot2 = x*x + y*y
,c = (a+b) * (a-b)
, and I think they're good, too. -
endolith about 11 yearsI agree with the second part of your answer, but not the first part. This is why you should post multiple answers if they are independent ideas.
-
WhyNotHugo about 11 yearsI can fit just 90 characters (columns) of code on my desktop screen. I use NO sidebars on my laptop to fit 70. This is due to poor eyesight. Not everyone can have 120 character wide screens (my desktop is 32", but my eyesight isn't getting any better). Also, the downvote is because your "example" isn't even PEP-8 compliant. If you're gonna complain about it, and post an example, post a compliant example.
-
WhyNotHugo about 11 yearsContinuation backslashes there are reduntant.
-
WhyNotHugo about 11 yearsIMHO, neither of these is readable. :)
-
Glenn Maynard about 11 years@Hugo: #1: Don't expect me to mangle my code because your configuration is broken. 90-column screens are not a reasonable development environment in 2013 (or 2010, when this was posted). #2: My example was copied straight from PEP-8, so congratulations for admitting to a clueless downvote.
-
Admin almost 11 yearsThat drives me absolutely insane when I see it. To me it makes similar but different lines look absolutely identical. When things are deceivingly similar but not quite the same what I want amped to the max is the fact that they ARE indeed different, and not some visual homogenization that makes it harder to tell them apart. IE: I often see your last example, minus the "/2" used, and it makes it really hard to see the formulas are symmetrical. When people similarly manage to mangle reciprocals, that's when I curl up under the desk and cry :) Matter of opinion, no offence meant
-
Mike Vella almost 11 yearsThis code is a perfect example of why 79 columns is a good rule, there are much better ways to implement the same logic. Usually more than 79 columns is a sign of poor design.
-
Mike Vella almost 11 yearsI think the reason they are both ugly is nothing to do with the spacing - you should use more variables and substitutions.
-
endolith over 10 years@ThE_JacO: I would say that this highlights the differences by putting them next to each other, in the same way that a diff tool does. If they weren't aligned, you might notice one difference while missing another.
-
marxin over 10 yearsFor me it's extremely unreadable. I see two logically separated columns. Much better is second approach, but still, for me first example is just ..better.
-
Scott Ritchie almost 10 yearsThe reason for the recommendation of spaces is, I believe, exactly to prevent you and your coworker from using different tab spacing amounts. You might style something that looks reasonable with 4 space indenting, but it won't look reasonable to him under 8 space indenting.
-
dotancohen almost 10 yearsThanks, Scott. Are you referring to the practice of vertically aligning
=
signs when multiple assignments are done on consecutive lines? If so, that can be done with spaces regardless of which characters were used for indentation. -
Kyle Strand over 9 yearsI do like being able to fit 2 to 3 separate source files side-by-side on one monitor, but I tend to agree with a previous coworker who said that while he appreciated the sentiment behind the 79-column restriction, it wasn't his "speed limit."
-
Bradley Kreider over 9 yearsIt drives me insane that this is against the rules, when the goal is better readability. Code is for humans, so it should read cleanly.
-
flying sheep over 9 years@Tshepang: well, if you add to
from foo import, bar, baz, ...
, you have the same problem. and nobody writesfrom foo import bar\nfrom foo import baz\n...
and those lines will be changed more often than top-level module imports! -
flying sheep over 9 yearsi also like pep-257-nn, or symmetric. the former has the advantage that the first line is distinguished as “short description” or header, the latter that it’s, well, symmetric.
-
tshepang over 9 years@flyingsheep for those, you do
from foo import (\n bar, \nbaz,\n)
-
Ski about 9 yearsRarely anyone is aligning
=
vertically in python. It is common however to align function parameters under(
, you'd have to use combination of tabs and spaces and it's just to easy to mess it up. And 8 spaces for indentation? Your colleague needs some rehabilitation. 4 spaces is accepted standard and he just needs to bear with it. What do you do if you got to pair program on someone else machine? -
dotancohen about 9 years@skyjur: Linus Torvalds only accepts patches with 8 spaces indentation for the Linux kernel. That's not Python, but it is feasible that someone who regularly deals with kernel code to prefer a similar environment in other contexts as well.
-
Colleen almost 9 yearsI actually strongly disagree with specifically @kitsu.eb 's comment. I think one line per module is the most readable and appropriate. If anything standard modules are where you would MOST want different lines.
-
IARI almost 9 years-1 because I dislike the reasons given in the Answer. I believe, it should only be about how well structured and readable code is - and that is so far to a great degree independent from the developement environment.
-
Glenn Maynard almost 9 yearsWrapping code at 80 columns results in unreadable code, so your -1 is sort of amusing.
-
paul23 over 8 yearsThis is a weakness in many modern day languages. Languages never seem to allow creation of extra operators to handle mathematical problems. (How I wish for the curl operator instead of having to constantly type out ugly functions, symbols are so much cleaner).
-
Jorjon about 8 yearsWell having all values aligned allows you to use column edit mode, found in many IDEs, and change values rather quickly.
-
Sembei Norimaki over 7 yearsI completely agree that alignment of operators in similar lines should be allowed
-
endolith over 7 years@GlennMaynard "90-column screens are not a reasonable development environment in 2013" Sure they are: sjbyrnes.com/wp-content/uploads/2012/03/spyder.jpg
-
Glenn Maynard over 7 years@endolith That's not a 90-column screen, that's a normal screen that the user has configured in a weird way (and a contrived way--who has a help panel bigger than his code?), and he can't expect everybody else to contort their code style for him.
-
endolith about 6 years@GlennMaynard "who has a help panel bigger than his code?" All of the thousands of people who use Spyder for scientific computing? It's the default (useful) layout.
-
Mausy5043 almost 6 yearsI prefer 32 spaces indentation :-p Especially when 2 suffice.
-
dotancohen almost 6 years@Mausy5043: Gotta love those wiiiiiiiiiiiiiiiiiiiiiiiidescreen monitors!
-
WestCoastProjects about 4 years@tshepang "Behaving badly" is this for real?? He is just stating a (reasonable!) programming preference.
-
WestCoastProjects about 4 yearsI do not use
pep8
at all - for many reasons. This is just one more now. -
WestCoastProjects about 4 years@ScottRitchie "prevent you and your coworker from using different tab spacing amounts". Is that for real? let's just throw ergonomics out the door. Do you like to stand or sit while typing? Do you prefer a 15 inch laptop or two 24 inch monitors? Well let's dictate which one for you to use.
-
PatrickT almost 3 yearsfor your
b_0
,b_1
example, I would add a+
sign to make the alignment with the-
sign. I don't know what rule that may violate... -
endolith almost 3 years@PatrickT Yeah I do that to trick the linter sometimes. I don't think it violates any rule
-
Steven Scott over 2 yearsThe main issue with 79 characters is very_long_descriptive_variable_names. In other languages these are not as much of a problem as you can write
object_with_very_long_name.method_with_very_long_name(argument_with_very_long_name, maybe_more_arguments_with_long_names)
using vertical whitespace to separate things. The extra importance of whitespace in python interferes with that strategy. I like 80 columns in C++ code, but prefer wider limits in python.