Effective Python 06 - 10

Click here for the first post, which contains the context of this series.

Item #06: Prefer multiple assignment unpacking over indexing.

Prefer

    first_name, middle_name, last_name = full_name

over

    first_name = full_name[0]
    middle_name = full_name[1]
    last_name = full_name[2]

Item #07: Prefer enumerate over range.

Prefer

    for i, item in enumerate(my_list):
        some_function(i, item)

over

    for i in range(len(my_list)):
        some_function(i, my_list[i])

Item #08: Use zip to process iterators in parallel.

Prefer

    for expected, actual in zip(expected_results, actual_results):
        assert expected == actual

over

    for i in range(len(expected_results)):
        # error prone if len(expected_results) != len(actual_results)
        assert expected_results[i] == actual_results[i]

Note that zip(A, B) iterates at most min(len(A), len(B)) times.

Item #09: Avoid else blocks after for and while loops.

Suppose that you want to check whether a list my_list contains an item target. Although this can be accomplished as follows

    for item in my_list:
        if item == target:
            print('target found')
            break
    else:
        print('target not found')

avoid doing this (perhaps using a flag).

Item #10: Prevent repetition with assignment expressions.

Consider the following common pattern

    info = get_info()
    if has_property(info):
        do_something_with(info)
    else:
        do_something_else()

It suggests that info is used beyond the scope of if. If it is not, then remove the ambiguity as follows

    if has_property(info := get_info()):
        do_something_with(info)
    else:
        do_something_else()

This way, the scope of info is restricted to if.