0

going thru a tutorial on python lists,I tried to write a python function which counts the number of occurrences of words that start with a specific letter

def count_occurrences(p,letter):
    count = 0
    for elem in p:
        if elem[0]==letter:
            count = count+1
    return count


>>>count_occurrences(['damon','jim','dennis'],'d')
2
>>>count_occurrences(['damon','jim'],'d')
1
>>>count_occurrences([],'d')
0

but, if I input a list containing the wrong types,say [1,2,3] ,it will throw a TypeError:'int' object is unsubscriptable since the code elem[0] is called on an int.

So,how do I handle this? should I use a try : except block or is there another way?

5 Answers 5

2

Try ... except gives you lots of flexibility to work with the code, and it will be a good idea,

Check this doc python exception handling

Exception handling provides the following advantages over ``traditional'' error management techniques:

separating Error Handling Code from ``regular'' one provides a way to separate the details of what to do when something out-of-the-ordinary happens from the normal logical flow of the program code; propagating Errors Up the Call Stack lets the corrective action to be taken at a higher level. This allows the corrective action to be taken in the method that calling that one where an error occurs; grouping Error Types and Error Differentiation allows to create similar hierarchical structure for exception handling so groups they in logical way.

Just an Example:

def count_occurrences(p,letter):
    count = 0
    for elem in p:
        try:    # Put you code which can throw exception in try Block
            if elem[0]==letter:
                count = count+1
        except Exception, ex: # You can catch specific exceptions if you want over here
              print ex.message  # Handle your exception here
              #raise   # The 'raise' statement with no arguments inside an error
                       # handler tells Python to re-raise the exception with the 
                       # original traceback intact

    return count
Sign up to request clarification or add additional context in comments.

2 Comments

Wherever possible you should avoid using bare Exception handling, ie. catching all Exception types. Rather handle what you expect to fail, and if something new creeps in you will be aware of it occuring imo.
@ChristianWitts: it's just an example, in the comment i have written you can catch specific exceptions.. :)
1

add an isinstance() condition to your if comdition to check the type of elem:

def count_occurrences(p,letter):
    count = 0
    for elem in p:
        if isinstance(elem,str) and elem[0]==letter: #if the first condition is true then
                                                     # only it'll check the next condition
            count = count+1
    return count

Comments

1

You have to decide what you want from your function:

def count_occurrences(p,letter):
    count = 0
    for elem in p:
        if isinstance(elem, basestring):
            if elem[0]==letter:
                count = count+1
        else:
            # you could do something else here or just ignore it, but it seems
            # that your function really needs a list of strings as argument 
            # so it would be an error to call it with anything else and it should 
            # not fail silently.
            raise TypeError("String expected")
    return count
  • Either it could ignore elements not matching the type. In that case you leave the else-section blank in the above example.
  • You want to only accept list-of-strings as argument. In that case, the above example is completely yours and it will even raise an error if an invalid type is passed.

See the python documentation on isinstance for further help.

On a sidenote try-except block outside the loop could bring more performance though.

2 Comments

isinstance(elem, (str,unicode)) -> isinstance(elem, basestring)
@astynax you're right. I looked for base_string, string_base, BaseString and so on cause I could not recall, but basestring didn't come into my mind.
0

More effectively written as:

sum(1 for i in sequence if i.startswith('d')) # or for single char i[0] == 'd'

If it's an invalid type, then you can either fail the operation using try/except, or filter out only the suitable type, eg:

sum(1 for i in sequence if isinstance(i, basestring) and i[0] == 'd')

Or to handle a fail because the list should be homogeneous:

   try:
       return sum(1 for i in sequence if i[0] =='d')
   except TypeError as e:
       pass # type doesn't have subscripting
   except IndexError as e:
       pass # may or may not be a str, but len() == 0

etc...

On a side note: using str.startswith('d') won't raise, so ''.startswith('d') returns False.

Comments

0

If you won't to use the try ... except you could do something like this:

if isinstance(elem[0],int): 
 { ... }

In that way, perharps, you can "skip" over that element.

A better solution would be test isinstance with the correct type and, in case of "test failure" skip the element.

So

if isinstance(elem,str) and elem[0]==letter:
 {...}

3 Comments

This will TypeError just the same, as elem might be unsubscriptable.
lots of other types are not subscriptable
@gnibbler: take a look at the "better solution" phrase

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.