Interesting "gotcha"

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Interesting "gotcha"

Michael H. Goldwasser

To start a new thread, I'm always trying to keep a list of some common
"gotchas" that beginning students run across when using Python, or
things that teachers should keep in mind when teaching with the
language. I have in mind commands that do not generate runtime errors,
but are likely to lead to logical errors that are not apparent to
students, and most of these are legal due to the very flexible nature
of the Python language.  Some classicss are

data.sort                  # no-op

data = data.sort()         # bye-bye data

result = result.upper      # probably not what you expect

if answer.isupper:         # always true ("but I entered a lowercase answer")


This semester, I ran across a new one that took me quite some time to
figure out what was happening.  This started with a habit that too
many students have of wanting to compare boolean values to True/False
literals, rather than just using the boolean as a condition.  That is,
students seem drawn to the syntax

  if answer.isupper() == True:

rather than the preferred

  if answer.isupper():

These complaints are more of style than substance, as the two
versions are logically equivalent.   But then a student came to me
with code that wasn't behaving.  The syntax they used was something
akin to


  if x > y == True:

however the condition was not being triggered, even when we verified
that x was indeed greater than y. You can try this out with explicit
values as follows.

>>> if 5 > 4 == True:
...     print "Good"
>>>

You will find that the body is not executed.  More directly, you can
look at the conditional value directly as

>>> 5 > 4
True
>>> 5 > 4 == True
False

This baffled me for an hour before finally seeing what was happening.
I'll leave this as a puzzle for readers (many of whom I'm sure will be
quicker than I was to see the solution).  For those who give up, I
offer the following link as a spoiler.
http://docs.python.org/reference/expressions.html#comparisons

With regard,
Michael

+-----------------------------------------------
| Michael H. Goldwasser, Ph.D.
| Associate Professor
| Director of Computer Science
| Dept. Mathematics and Computer Science
| Saint Louis University
| 220 North Grand Blvd.
| St. Louis, MO 63103-2007
|
| Office: Ritter Hall 108
| Email:  [hidden email]
| URL:    http://cs.slu.edu/~goldwasser
| Phone:  (314) 977-7039
| Fax:    (314) 977-1452

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

Christian Mascher
Hi,

I really like it that python allows me to write

if 10 < x <=  b:
     ...

impossible in many other languages.
But all things come at a cost:

>
>   if x > y == True:
>

I think this is a real gotcha, because it might get you, because you
_know too much_:
 >>> if 4:
        print True

       
True
 >>>
So all things different from 0, '', ... are considered True by python.
But.....

spoiler ahead ;-)
 >>> 4==True

False
 >>>

Cheers

Christian
_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

John Zelle
Hi,

I agree that the behavior of booleans in Python can sometimes lead to subtle errors, but I think it's important to stress to students that writing things like:

if x>y == True:

is _really_ bad style. After pointing that out, I start taking points away for doing this. Code like this shows that the writer really does not understand Boolean types and their use. Expressions like this can cause subtle errors in just about any language, even those that are statically typed to prevent this sort of confusion. In Java, (x>y==true) is not a valid expression, so it won't compile. But consider this loop that seems to use done as a boolean flag::

boolean done = false;
while(done = false){
    // do some stuff here
}

The loop body will never execute. This sort of error in a strongly typed language is often very hard to spot, since we assume the compiler should catch it. If the condition is simply written as:

while(!done){

then you can't go wrong.

My point is that while I agree this is a "gotcha" in Python, there are similar gotchas in just about all languages. The real culprit in the original example is poor coding style, not the language semantics per se.

--John

________________________________________
From: edu-sig-bounces+john.zelle=[hidden email] [edu-sig-bounces+john.zelle=[hidden email]] on behalf of Christian Mascher [[hidden email]]
Sent: Tuesday, March 29, 2011 10:12 AM
To: [hidden email]
Subject: Re: [Edu-sig] Interesting "gotcha"

Hi,

I really like it that python allows me to write

if 10 < x <=  b:
     ...

impossible in many other languages.
But all things come at a cost:

>
>   if x > y == True:
>

I think this is a real gotcha, because it might get you, because you
_know too much_:
 >>> if 4:
        print True


True
 >>>
So all things different from 0, '', ... are considered True by python.
But.....

spoiler ahead ;-)
 >>> 4==True

False
 >>>

Cheers

Christian
_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

kirby urner-4
In reply to this post by Michael H. Goldwasser
On Mon, Mar 28, 2011 at 10:06 PM, Michael H. Goldwasser <[hidden email]> wrote:

To start a new thread, I'm always trying to keep a list of some common
"gotchas" that beginning students run across when using Python, or
things that teachers should keep in mind when teaching with the
language. 

Sincere applause -- exactly the kind of thread edu-sig should include
in the weave.

This mystr.isupper( ) == True:

stuff is quite common.  One also gets veterans of other languages
wanting to use while instead for for loops:

cnt = 0
while cnt < len(mylist):
    theword = mylist[cnt]
    of theword.isupper( ) == True:
        is_upper.append(theword)
    cnt += 1

instead of

is_upper = [ theword for theword in mylist if theword.isupper() ]

I was at one of David Goodger's talks which was all about 
getting more idiomatic. 

Knowing the default behavior of dicts means you know you
can say 

for key in thedict:

instead of 

for key in thedict.keys():

Sometimes I'll think a student is using an idiom that looks odd
and so isn't "Pythonic" (as if I were the only judge). Like:

mydict.update({key:value}) 

instead of 

mydict[key] = value

but then I'll do a search and see enough authors using the idiom 
to update my own ideas of what's idiomatic.

Teachers have a privileged position, getting to see the
same solutions over and over but in slightly (or greatly)
different styles.

edu-sig makes a useful repository for those wishing to
share from this perspective.

Kirby


_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

Carl Cerecke-4
In reply to this post by Michael H. Goldwasser
My experience of confusing boolean expressions was the code:

>>> 1 == 2 in [2, False]
False

which, when parenthesised the two possible ways
>>> (1 == 2) in [2, False]
True
>>> 1 == (2 in [2, False])
True
results in sensible values (although the second one's sensibility is debatable)

I couldn't figure it out quickly either. In fact, I ended up decompiling to byte code to figure out what was going on.

As far as other 'gotcha's in addition to the ones already mentioned:

Calling a file the same name as a module in the standard library. Import <name> will get the local file, not the stdlib one, which is confusing if you wanted the stdlib one.

I've noticed that students will somtimes put import statements inside a function - right before they need to use whatever they imported:
def area(r):
  import math
  return math.pi*r*r

Cheers,
Carl.

On 29 March 2011 18:06, Michael H. Goldwasser <[hidden email]> wrote:

To start a new thread, I'm always trying to keep a list of some common
"gotchas" that beginning students run across when using Python, or
things that teachers should keep in mind when teaching with the
language. I have in mind commands that do not generate runtime errors,
but are likely to lead to logical errors that are not apparent to
students, and most of these are legal due to the very flexible nature
of the Python language.  Some classicss are

data.sort                  # no-op

data = data.sort()         # bye-bye data

result = result.upper      # probably not what you expect

if answer.isupper:         # always true ("but I entered a lowercase answer")


This semester, I ran across a new one that took me quite some time to
figure out what was happening.  This started with a habit that too
many students have of wanting to compare boolean values to True/False
literals, rather than just using the boolean as a condition.  That is,
students seem drawn to the syntax

 if answer.isupper() == True:

rather than the preferred

 if answer.isupper():

These complaints are more of style than substance, as the two
versions are logically equivalent.   But then a student came to me
with code that wasn't behaving.  The syntax they used was something
akin to


 if x > y == True:

however the condition was not being triggered, even when we verified
that x was indeed greater than y. You can try this out with explicit
values as follows.

>>> if 5 > 4 == True:
...     print "Good"
>>>

You will find that the body is not executed.  More directly, you can
look at the conditional value directly as

>>> 5 > 4
True
>>> 5 > 4 == True
False

This baffled me for an hour before finally seeing what was happening.
I'll leave this as a puzzle for readers (many of whom I'm sure will be
quicker than I was to see the solution).  For those who give up, I
offer the following link as a spoiler.
http://docs.python.org/reference/expressions.html#comparisons

With regard,
Michael

+-----------------------------------------------
| Michael H. Goldwasser, Ph.D.
| Associate Professor
| Director of Computer Science
| Dept. Mathematics and Computer Science
| Saint Louis University
| 220 North Grand Blvd.
| St. Louis, MO 63103-2007
|
| Office: Ritter Hall 108
| Email:  [hidden email]
| URL:    http://cs.slu.edu/~goldwasser
| Phone:  (314) 977-7039
| Fax:    (314) 977-1452

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig


_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

Kirby Urner-6

What is a Python module? #==========================

Common answer is "a file containing Python source code?",
but I'm questioning whether that's sufficient definition. 

How about an importable .pyc or .pyd, with no .py in the
picture.  That's a module too, no?

** Import Star #====================================

When is 
import *
a good idea?  

There's all this righteous moralistic hoopla that gets built up 
against specific idioms, to where eval( ) appears to be fighting 
for its very existence...  Mary wants to keep her little lambda.

So I'd rather phrase these in the positive, as in when IS it
a good idea... e.g. to use semi-colons between statements.

** Another student question:  #=========================

Why does all([]) return True by default?  Is this a case
of half full versus half empty?

** Correcting a misconception  #========================

No, docstrings do NOT have to be triple quoted.

Kirby


_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

Mokurai
In reply to this post by Carl Cerecke-4
So 'in' is a comparison "operator", is it? I am annoyed at how long it
took me to verify that Python treats it as such, and I am also annoyed
that it is so.

http://docs.python.org/tutorial/datastructures.html
5.7. More on Conditions¶

The conditions used in while and if statements can contain any
operators, not just comparisons.

The comparison operators in and not in check whether a value occurs
(does not occur) in a sequence.

I never cared for the misleading a<b<c notation anyway, and won't use it.

On Tue, Mar 29, 2011 at 19:09, Carl Cerecke <[hidden email]> wrote:

> My experience of confusing boolean expressions was the code:
>
>>>> 1 == 2 in [2, False]
> False
>
> which, when parenthesised the two possible ways
>>>> (1 == 2) in [2, False]
> True
>>>> 1 == (2 in [2, False])
> True
> results in sensible values (although the second one's sensibility is
> debatable)
>
> I couldn't figure it out quickly either. In fact, I ended up decompiling to
> byte code to figure out what was going on.
>
> As far as other 'gotcha's in addition to the ones already mentioned:
>
> Calling a file the same name as a module in the standard library. Import
> <name> will get the local file, not the stdlib one, which is confusing if
> you wanted the stdlib one.
>
> I've noticed that students will somtimes put import statements inside a
> function - right before they need to use whatever they imported:
> def area(r):
>   import math
>   return math.pi*r*r
>
> Cheers,
> Carl.
>
> On 29 March 2011 18:06, Michael H. Goldwasser <[hidden email]> wrote:
>>
>> To start a new thread, I'm always trying to keep a list of some common
>> "gotchas" that beginning students run across when using Python, or
>> things that teachers should keep in mind when teaching with the
>> language. I have in mind commands that do not generate runtime errors,
>> but are likely to lead to logical errors that are not apparent to
>> students, and most of these are legal due to the very flexible nature
>> of the Python language.  Some classicss are
>>
>> data.sort                  # no-op
>>
>> data = data.sort()         # bye-bye data
>>
>> result = result.upper      # probably not what you expect
>>
>> if answer.isupper:         # always true ("but I entered a lowercase
>> answer")
>>
>>
>> This semester, I ran across a new one that took me quite some time to
>> figure out what was happening.  This started with a habit that too
>> many students have of wanting to compare boolean values to True/False
>> literals, rather than just using the boolean as a condition.  That is,
>> students seem drawn to the syntax
>>
>>  if answer.isupper() == True:
>>
>> rather than the preferred
>>
>>  if answer.isupper():
>>
>> These complaints are more of style than substance, as the two
>> versions are logically equivalent.   But then a student came to me
>> with code that wasn't behaving.  The syntax they used was something
>> akin to
>>
>>
>>  if x > y == True:
>>
>> however the condition was not being triggered, even when we verified
>> that x was indeed greater than y. You can try this out with explicit
>> values as follows.
>>
>> >>> if 5 > 4 == True:
>> ...     print "Good"
>> >>>
>>
>> You will find that the body is not executed.  More directly, you can
>> look at the conditional value directly as
>>
>> >>> 5 > 4
>> True
>> >>> 5 > 4 == True
>> False
>>
>> This baffled me for an hour before finally seeing what was happening.
>> I'll leave this as a puzzle for readers (many of whom I'm sure will be
>> quicker than I was to see the solution).  For those who give up, I
>> offer the following link as a spoiler.
>> http://docs.python.org/reference/expressions.html#comparisons
>>
>> With regard,
>> Michael
>>
>> +-----------------------------------------------
>> | Michael H. Goldwasser, Ph.D.
>> | Associate Professor
>> | Director of Computer Science
>> | Dept. Mathematics and Computer Science
>> | Saint Louis University
>> | 220 North Grand Blvd.
>> | St. Louis, MO 63103-2007
>> |
>> | Office: Ritter Hall 108
>> | Email:  [hidden email]
>> | URL:    http://cs.slu.edu/~goldwasser
>> | Phone:  (314) 977-7039
>> | Fax:    (314) 977-1452
>>
>> _______________________________________________
>> Edu-sig mailing list
>> [hidden email]
>> http://mail.python.org/mailman/listinfo/edu-sig
>
>
> _______________________________________________
> Edu-sig mailing list
> [hidden email]
> http://mail.python.org/mailman/listinfo/edu-sig
>
>



--
Edward Mokurai (默雷/धर्ममेघशब्दगर्ज/دھرممیگھشبدگر ج) Cherlin
Silent Thunder is my name, and Children are my nation.
The Cosmos is my dwelling place, the Truth my destination.
http://www.earthtreasury.org/
_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: Interesting "gotcha"

kirby urner-4
On Wed, Mar 30, 2011 at 11:31 AM, Edward Cherlin <[hidden email]> wrote:
So 'in' is a comparison "operator", is it? I am annoyed at how long it
took me to verify that Python treats it as such, and I am also annoyed
that it is so.

http://docs.python.org/tutorial/datastructures.html
5.7. More on Conditions¶

The conditions used in while and if statements can contain any
operators, not just comparisons.
 
As you no doubt know, in triggers the rib __contains__ in the cosmic 
backbone of Python's special names list, whereas operators like ==,
> and < trigger their own specially named reflexes:

>>> class Foo:
def __contains__(self, value):
print ("Yes {} is in the bar".format(value))
return True

>>> bar = Foo()
>>> "Joe" in bar
Yes Joe is in the bar
True


>>> class Average:
def __lt__(self, value):
print("Yes {} is better than Average".format(value))
return True

>>> bar = Average()
>>> "Joe's bar" > bar
Yes Joe's bar is better than Average
True
>>> 


The comparison operators in and not in check whether a value occurs
(does not occur) in a sequence.

I never cared for the misleading a<b<c notation anyway, and won't use it.


heretic!

Kirby



_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig