4

I'm a bit stumped here. Here's a piece of Python code:

try:
    if parse[index+1][0] != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]
except IndexError:
    warning("Reached end of file. No next element")
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Basically I want these two actions (addition of individual_services_cur list to individual_services list and clearing of individual_services_cur list) to take place either if the next element in parse is not "5" or if it doesn't exist (basically it is the end of file).

I am wondering if there is a more elegant (maybe even, as they say, "pythonic") way to write this code, for example, without the need to write these two actions twice. I couldn't think of any good solution with finally or else statements, and it seems that I cannot get rid of try statement because once the end of file is reached, the IndexError exception is inevitably raised.

3
  • It appears the the two things you want to happen don't depend on the if parse[index+1][0] != "5" at all -- so just leave it out (and the try/except) and perform the two of them. Commented Jan 23, 2015 at 14:02
  • @martineau: that's not true, if the element is say "4" then the code isn't run Commented Jan 23, 2015 at 14:04
  • @Highstaker does any of the answer below helped you? If yes, select one as your answer. Commented Jan 23, 2015 at 16:49

5 Answers 5

3

You can use an intermediate variable to perform the checks you need.

try:
    value_to_check = parse[index+1][0]

except IndexError:
    warning("Reached end of file. No next element")
    value_to_check = None
finally:
    if value_to_check != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]
Sign up to request clarification or add additional context in comments.

Comments

2

Another idea:

update_i_s = True

try:
    update_i_s= parse[index+1][0] != "5"
except IndexError:
    warning("Reached end of file. No next element")
finally:
    if update_i_s:
        individual_services.append([individual_services_cur]) if flag
        individual_services_cur=[]

flag=True is only needed for the case that there is only one line in the file, and only needs to be set once at the beginning (so don't go putting it inside any loops).


EDIT:

By the way, if there is a possibility the finally block could fail, you might want to do something like this:

try:
    try:
        update_i_s= parse[index+1][0] != "5"
    except IndexError:
        warning("Reached end of file. No next element")
    finally:
        if update_i_s:
            individual_services.append([individual_services_cur]) if flag
            individual_services_cur=[]
except Exception:
    warning("failed to update individual_services")
    raise

Comments

1

You could assign a variable in both cases and then check it once.

badstuff = False
try:
    if parse[index+1][0] != "5":
        badstuff = True
except IndexError:
    warning("Reached end of file. No next element")
    badstuff = True

if badstuff:
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

If it suits you, you could put the if badstuff: in a finally block, depending on what the rest of your code is doing.

Alternatively, put the individual_services stuff in a function, and call it in both places.

2 Comments

I thought about using a separate variable like this, but it felt like a not very "pythonic" way of doing it. Maybe I shouldn't care much about it though...
Not worrying too much about it being pythonic is very pythonic.
0

How about

last = len(parse) - 1

if index == last or parse[index + 1][0] != "5":
    individual_services.append(individual_services_cur)
    individual_services_cur = []

Comments

0

Or thinking outside the box a bit:

if index + 1 not in (index for index, value in enumerate(parse) if value[0] == '5'):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Where (index for index, value in enumerate(parse) if value[0] == '5') is a generator that yields the line number of each line that has a '5' as the first character. It is equivalent to this:

def has_5s(p):
    '''Yield line numbers that begin with a 5'''
    for index, line in enumerate(p):
        yield index if line[0] == '5'

if index + 1 not in has_5s(parse):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

You are simply checking to see if the following line number (line + 1) is one of these line numbers yielded by the generator. Since enumerate and the generator itself are lazy this should be very fast.

Comments

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.