Pylint: Add suggestion for `len-as-condition` message.

Created on 2 Apr 2017  路  10Comments  路  Source: PyCQA/pylint

Most helpful comment

This was apparently derived from PEP8, but note that PEP8 also says "a foolish consistency is the hobgoblin of small minds". It goes too far to claim that using len(..) == 0 as a condition is incorrect. There is a theoretical gain in efficiency, when len() is somehow an expensive operation while bool() can short-circuit, but none of the Python builtin datastructures work that way (len() gets the length from the ob_size attribute, no traversal is needed). Moreover, with small lists this wouldn't be significant, and the consistency in the following case is arguably more important:

if len(a) == 0: pass
elif len(a) == 1: pass
elif len(a) == 2: pass
else: pass

Another example is that assert len(errors) == 0 is arguably more intuitive than assert not errors.
IMHO this test should not be on by default.

All 10 comments

In short (and to make the issue self-sufficient), writing len(SEQUENCE) == 0 or similar expressions such aslen(SEQUENCE) > 0 as a condition value triggers C1801 with the message "Do not use len(SEQUENCE) as condition value", which can give a wrong (or at the very least, unclear) impression.

I created that question because I ended up wondering whether calling len on a collection or sequence had unexpected consequences in my code, while C1801 was actually attempting to warn me about the idiomatic form of checking for empty collections: if SEQ: and if not SEQ: do not trigger the warning, but nothing in the message advised me to write this.

This was apparently derived from PEP8, but note that PEP8 also says "a foolish consistency is the hobgoblin of small minds". It goes too far to claim that using len(..) == 0 as a condition is incorrect. There is a theoretical gain in efficiency, when len() is somehow an expensive operation while bool() can short-circuit, but none of the Python builtin datastructures work that way (len() gets the length from the ob_size attribute, no traversal is needed). Moreover, with small lists this wouldn't be significant, and the consistency in the following case is arguably more important:

if len(a) == 0: pass
elif len(a) == 1: pass
elif len(a) == 2: pass
else: pass

Another example is that assert len(errors) == 0 is arguably more intuitive than assert not errors.
IMHO this test should not be on by default.

@PCManticore why was this closed?

@acannon828 #1473 was merged. Although it does not provide an actual suggestion per se, this clears the ambiguity that led to this issue in the first place.

By the way, none of collections.abc classes states __bool__ method. In other words, how can I be sure that I can use bool(seq) if I know that it's a collections.abc.Collection? Moreso, some libraries declire that it's forbidden to check bool(collection) for their classes even they follow and "implement" this interface.

I think we should take PEP literally here. It says "don't use if len(seq) (relying on the "truthiness" of integers), it doesn't say "don't use len(seq) == n)".

@timokau I'm not sure I understand your statement. Regarding the use of len, PEP 8 comes down to this, verbatim:

  • For sequences, (strings, lists, tuples), use the fact that empty sequences are false.

Yes:

if not seq:`
if seq:

No:

if len(seq):
if not len(seq):

The statement "don't use len(seq)" (as a condition value) seems to have come from PyLint rather than PEP. The real confusion comes when the lint len-as-condition is triggered even when we do not assume the truthiness of anything but the output of the comparison operator: len(seq) == 0 or len(seq) > 0 would just raise "don't use len(seq) as condition value" all the same.

Yes that is exactly my point. I think there should be no warning when explicitly comparing the length with something.

Ah, I see your point now. I agree that triggering the lint with the condition len(seq) but _not_ with len(seq) == 0 would be less surprising. On the other hand, one might still argue that by writing len(seq) == 0, we're not relying on the "truthiness" of the sequence, as recommended by these guidelines.

It might be worth filing about the behaviour of this lint in a separate issue, since this one was initially focused on the lint's message, which has since then been improved with #1473.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Hubro picture Hubro  路  3Comments

z4y4ts picture z4y4ts  路  3Comments

PCManticore picture PCManticore  路  3Comments

glmdgrielson picture glmdgrielson  路  3Comments

pylint-bot picture pylint-bot  路  3Comments