[Tutor] Dividing a float derived from a string

Danny Yoo dyoo at hashcollision.org
Fri Nov 21 00:37:05 CET 2014


On Thu, Nov 20, 2014 at 3:05 PM, Stephanie Morrow <svmorrow at gmail.com> wrote:
> What else could I do in that testing portion that would allow for a decimal
> point?  In order for a decimal to be True, it would have to accept both the
> digits and the decimal point.


Let's tackle a problem that's tangent but related, in the sense that
it'll help you practice writing functions that return useful results.

Let's say that we want to write a function on strings that returns
True if the string looks like a "sentence".

For the purposes of this example, we'll say that a string looks like a
sentence if it starts with a capital letter, and it ends with a
period.


So we'd like to see:


#######################
>>> isSentence("Hello world.")
True
>>> isSentence("How now blue cow")
False
>>> isSentence("hi.")
False
>>> isSentence("Bye!")
False
>>> isSentence("Gesundheit.")
True
>>> isSentence("")
False
##########################


Think about how you'd write this.  Try it.  Read the rest below after
you've tried.

















There are a few ways to write out a function definition for
isSentence().  Let me show a few of these.

There are two things we need to check for.

  * The first part of the string has to be uppercased, and
  * The last part of the string has to be a period.

We can express the first condition on a string 's' as the following:

    s[0].isupper()

For example:

##################
>>> 'fun'[0].isupper()
False
>>> 'Fun'[0].isupper()
True
##################


The second condition, that the last part of a string 's' is a period,
can be expressed as:

    s[-1] == '.'


Given those two ideas, we can say that something is a sentence if it
fulfills both those expressions.  In short, we can say this with an
"and", which takes two expressions and returns True if both of them
are true.

################################
def isSentence(s):
    return s[0].isupper() and s[-1] == '.'
################################


We can try this out and see if it's reasonably close.

(Note that I haven't said that it's right.  There's a good reason I'm
not saying that yet.)

#########################
>>> isSentence("Howdy.")
True
>>> isSentence("Sayonara")
False
#########################


It turns out we can say isSentence() in a few other ways.  We can use
a case analysis:

###############################
def isSentence(s):
     if s[0].isupper():
        if s[-1] == '.':
            return True
        else:
            return False
    else:
        return False
###############################

This behaves the same as the one before.  I prefer the earlier because
it reads better to me, and doesn't feel as step-wise.  But this works
too.


Now, there was a caveat before about isSentence not quite being right.
That's because it _presumes_ that there's a first and last character:
that presumption's broken if the string is empty.

######################################
>>> isSentence("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in isSentence
IndexError: string index out of range
######################################

Ooops.


So we need to make a revision to what we want to check:

There are _three_ things we need to check for.

   * The string is at least two characters long,
   * The first part of the string has to be uppercased, and
   * The last part of the string has to be a period.


And adding yet another expression to be tested isn't too bad:


##########################################
def isSentence(s):
    return len(s) >= 2 and s[0].isupper() and s[-1] == '.'
###########################################


This can also be expressed this way:

###########################################
def isSentence(s):
    if len(s) < 2:
        return False
    return s[0].isupper() and s[-1] == '.'
###########################################

and you might prefer this, because it's expressed in a way where the
unusual case is set aside apart from the common case.  So it might
read better for human beings.



The reason this is related to the question on recognizing numbers with
a decimal point is because the case analysis is about of equal
complexity.  You need to check for a few things when defining a
function like looksLikeNumber():

   * That the string is all digits.

   or

   * That the string has a decimal point,
   * That the left side of the string is all digits, and
   * That the right side of the string is all digits.

Defining a helper function that does these things is not too bad.  It
does involve either a few conditional statements, or a robust use of
"and"s and "or"s.


More information about the Tutor mailing list