On Mon, 03 Jun 2013 18:37:24 -0700, Rick Johnson wrote:
> On Sunday, June 2, 2013 1:58:30 PM UTC-5, Steven D'Aprano wrote:
>> On Sun, 02 Jun 2013 10:04:00 -0700, Rick Johnson wrote:

>> > A "wise programmer" may think he's solved the problem by writing a
>> > function called "debugprint" that looks like this:
>> > >     def debugprint(*args):
>> >         if DEBUG == True:
>> >             print(*args)
>>
>> No no no, that's not how you do it. It should be:
>>     if DEBUG == True == True:
>>
>> Wait, no, I got that wrong. It should be:
>>     if DEBUG == True == True == True:
>>
>> Hang on, I've nearly got it!
>>     if DEBUG == True == True == True == True:
>>
>> Or, you could program like a professional, and say:
>>     if DEBUG:
> 
> Obviously you don't appreciate the value of "explicit enough".
> 
>   if VALUE:
> 
> is not explicit enough, however

Consider a simple thought experiment. Suppose we start with a sequence of 
if statements that begin simple and get more complicated:

if a == 1: ...

if a == 1 and b > 2*c: ...

if a == 1 and b > 2*c or d%4 == 1: ...

if a == 1 and b > 2*c or d%4 == 1 and not (d**3//7)%3 == 0: ...


I don't believe that any of these tests are improved by adding an 
extraneous "== True" at the end:

if (a == 1) == True: ...

if (a == 1 and b > 2*c) == True: ...

if (a == 1 and b > 2*c or d%4 == 1) == True: ...

if (a == 1 and b > 2*c or d%4 == 1 and not (d**3//7)%3 == 0) == True: ...

At some point your condition becomes so complicated that you may wish to 
save it as a separate variable, or perhaps you need to check the flag in 
a couple of places and so calculate it only once. Moving the flag out 
into a separate variable doesn't make "== True" any more useful or 
helpful.

flag = a == 1
if flag == True: ...


But even if it did, well, you've just entered the Twilight Zone, because 
of course "flag == True" is just a flag, so it too needs to be tested 
with "== True":

flag = (a == 1) == True
if flag == True: ...

but that too is just a flag so it needs more "explicitness"... and so on 
forever. This conclusion is of course nonsense. Adding "== True" to your 
boolean tests isn't helpful, so there's no need for even one, let alone 
an infinite series of "== True".

"if flag" is as explicit as it needs to be. There's no need to 
artificially inflate the "explicitness" as if being explicit was good in 
and of itself. We don't normally write code like this:

n += int(1)

just to be explicit about 1 being an int. That would be redundant and 
silly. In Python, 1 *is* an int.


[...]
>   if lst:
> 
> I don't like that because it's too implict. What exactly about the list
> are we wanting to test?

If you are unfamiliar with Python, then you have to learn what the 
semantics of "if lst" means. Just as you would have to learn what 
"if len(lst) > 0" means.


> I prefer to be explicit at the cost of a few keystrokes:
> 
>   if len(lst) > 0:

This line of code is problematic, for various reasons:

- you're making assumptions about the object which are unnecessary;

- which breaks duck-typing;

- and risks doing too much work, or failing altogether.

You're looking up the length of the lst object, but you don't really care 
about the length. You only care about whether there is something there or 
not, whether lst is empty or not. It makes no difference whether lst 
contains one item or one hundred million items, and yet you're asking to 
count them all. Only to throw that count away immediately!

Looking at the length of a built-in list is cheap, but why assume it is a 
built-in list? Perhaps it is a linked list where counting the items 
requires a slow O(N) traversal of the entire list. Or some kind of lazy 
sequence that has no way of counting the items remaining, but knows 
whether it is exhausted or not.

The Python way is to duck-type, and to let the lst object decide for 
itself whether it's empty or not:

if lst: ...


not to make assumptions about the specific type and performance of the 
object.


> Consider the following:
> 
>  What if the symbol `value` is expected to be a list, however, somehow
>  it accidentally got reassigned to another type. If i choose to be
>  implicit and use: "if value", the code could silently work for a type i
>  did not intend, therefore the program could go on for quite some time
>  before failing suddenly on attribute error, or whatever.

`if len(lst) > 0` also works for types you don't intend. Any type that 
defines a __len__ method which returns an integer will do it.

Tuples, sets and dicts are just the most obvious examples of things that 
support len() but do not necessarily support all the things you might 
wish to do to a list.



> However, if i choose to be explicit and use:
> 
>   "if len(VALUE) > 0:
> 
> then the code will fail when it should: at the comparison line.

Except of course when it doesn't.


> Because
> any object that does not provide a __len__ method would cause Python to
> raise NameError.

TypeError.



> By being "explicit enough" i will inject readability and safety into my
> code base. 

Unnecessary verbosity and redundancy, unnecessary restrictions on the 
type of the object, and unjustifiable assumptions about the cost of 
calling len().


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to