
Nick Parlante wrote:
Hi there python-ideas - I've been teaching Python as a first programming language for a few years, and from that experience I want to propose a change to PEP8. I'm sure the default position for PEP8 is to avoid changing it. However, for this one rule I think a good case can be made to make it optional, so let me know what you think. Let me start with what I've learned from teaching students in Java and now in Python. In Java, you use == for ints, but you need to use equals() for strings. Of course students screw this up constantly, using == in a context that calls for equals() and their code does not work right. Then for Java arrays a different comparison function is required, and so it goes. To teach comparisons in Python, I simply say "just use ==" - it works for ints, for strings, even for lists. Students are blown away by how nice and simple this is. This is how things should work. Python really gets this right. So what is the problem? The problem for Python is what I will call the "mandatory-is" rule in PEP8, which reads: Comparisons to singletons like None should always be done with is or is not, never the equality operators. For the students, this comes up in the first week of the course with lines like "if x == None:" which work perfectly with == but should use is/is-not for PEP8 conformance. My guess is that this rule is in PEP8 because, within a Python implementation, it is within the programmer's mental model that, say, False is a singleton. The mandatory-is rule is in PEP8 to reinforce that mental model by requiring the is operator. Plus it probably runs a tiny bit faster. However, for "regular" Python code, not implementing Python, forcing the use of is instead of the simpler == is unneeded and unhelpful (and analogously forcing "is not" when != works correctly). What is the benefit of forcing the is operator there? I would say it spreads an awareness of the details of how certain values are allocated within Python. That's not much of a benefit, and it's kind of circular. Like if programmers were permitted to use ==, they wouldn't need to know the details of how Python allocates those values. Being shielded from implementation details is a Python strength - think of the Java vs. Python story above. Is Java better because it builds an awareness in the programmer of the different comparison functions for different types? Of course not! Python is better in that case because it lets the programmer simply use == and not think about those details. Understanding the singleton strategy is important in some corners of coding, but forcing the is operator on all Python code is way out of proportion to the benefit. As a practical matter, the way this comes up for my students is that IDEs by default will put warning marks around PEP8 violations in their code. Mostly this IDE-coaching is very helpful for students learning Python. For example, It's great that beginning Python programmers learn to put one space around operators right from the first day. Having taught thousands of introductory Python students, the one PEP8 rule that causes problems is this mandatory-is rule. As a teacher, this is especially jarring since the "just use ==" rule is so effortless to use correctly. In contrast, the mandatory-is rule adds a little pause where the programmer should think about which comparison operator is the correct one to use. It's not hard, but it feels unnecessary. As a contrasting example, in the language C, programmers need to understand == vs. is right from the first day. You can't get anything done in C without understanding that distinction. However that is just not true for regular (not-Python-implementation) Python code, where == works correctly for the great majority of cases. Here is my proposal: Add the following parenthetical to the mandatory-is rule: (this rule is optional for code that is not part of an implementation of Python). So in effect, programmers outside of a Python implementation can choose to use == or is for the "if x == None:" case. In this way, PEP8 conforming code before the change is still conforming. Moving forward, I would expect that regular code will trend towards using == in such a case, reserving is for the rare cases where it is needed for correctness. PEP8 was originally just for Python implementations, so why is this change needed? Because as a practical matter, the vast majority of code that is using PEP8 is not part of a Python implementation. This may not have been the original mission of PEP8, but it is how things have worked out. Now we are in a situation where the rules in PEP8 are sent out to this ocean of Python programmers of many different ability levels writing regular code that is not a Python implementation. One could imagine a separate PEP800 style guide for regular code, but we don't need to do that, because in almost all cases PEP8 works great for regular code. I have taught thousands of new Python programmers, and the only place where PEP8 serves them poorly is this mandatory-is rule. Therefore instead of a separate style guide for regular code, I propose an exception for this one problem rule. Ultimately this comes down to the question - should PEP8 push regular, not-Python-implementation code to use is for singletons in cases where == works perfectly? Seeing how effortless it is for programmers to use == as their first choice, I think PEP8 should allow that practice. Best, Nick
I've only really seen this in practice in sqlalchemy and it has espr.is_(None) and expr.is_not_(None) and ~expr for expr == None and expr != None and expr == True