0
def copy_me(input_list):
    ''' (list) -> list
    This function will copy the list and will do the following to it:
    change every string into an upper case, increase the value of every
    integer and float by 1, negate every boolean and replace lists with the
    word 'List'. After the modifications are made, the copied list will be
    returned. (The original inputted list won't be mutated)
    REQ: The list must only contain the following data types: str, int,
    float, bool, list.

    >>> copy_me(['hi', 1, 1.5, True, ['sup', 123])
    ['HI', 2, 2.5, False, 'List']
    '''
    # Copy the list
    copied_list = input_list.copy()

    # Go through each element of list
    for index, element in enumerate(copied_list):
        print(type(element))

        if (type(element) == str):
            copied_list[index] = element.upper()
        elif (type(element) == int or float):
            copied_list[index] = element + 1
        elif (type(element) == bool):
            if (element == True):
                copied_list[index] = False
            elif (element == False):
                copied_list[index] = True
    print(copied_list)

doing something like:

>>> copy_me([True])
[2]

That makes no sense to me. Can anyone explain why and how I can get it to return False as the value?

mgilson
  • 300,191
  • 65
  • 633
  • 696
Krio
  • 19
  • 6
  • `type(element) == int or float` [doesn't mean what you think it means](http://stackoverflow.com/q/15112125/748858). That gets parsed as `(type(element) == int) or float)`. Since `float` is truthy, that branch will _always_ execute unless a branch above it already executed... – mgilson Oct 30 '16 at 06:53
  • Shouldn't float be false in the if statement regardless? But okay I think I get it thanks! – Krio Oct 30 '16 at 06:55
  • Nope. In python _most_ things are truthy (including all builtin types). – mgilson Oct 30 '16 at 06:59
  • Also, based on the "REQ" part, it looks like you're missing a chance to use recursion (e.g. if you get a list that holds another list!) :-) – mgilson Oct 30 '16 at 07:05
  • haven't learned recursion yet D:, but it should handle it properly where it'll get rid of the list entirely and replace it with 'List' ;D – Krio Oct 30 '16 at 07:20

2 Answers2

2

There's a number of things here that are problematic. The first is:

type(element) == int or float

This has been asked about multiple times so I won't answer in depth here. The problem is that the expression is parsed as (type(element) == int) or float) -- and since float is truthy, that expression is always going to be truthy. The fix is something like 1:

type(element) == int or type(element) == float

This should be enough to get your code working, however, isinstance is much more idiomatic and can be used to clean this up significantly:

if isinstance(element, str):
    copied_list[index] = element.upper()
elif isinstance(element, bool):
    copied_list[index] = not element  # cleaner negation :-)
elif isinstance(element, (int, float)):  # numbers.Number might even be better...
    copied_list[index] = element + 1

Notice that I put the bool check before the int, float check. The reason for this is because bool is an int subclass (which also explains how you got a 2 in your initial code:

True + 1 == 2

1Generally, I'd also advise using isinstance(x, y) rather than type(x) == y

Community
  • 1
  • 1
mgilson
  • 300,191
  • 65
  • 633
  • 696
0

You problem is in the condition:

type(element) == int or float

You are missing parentheses around the "int or float" part. So what the condition is checking is: 1. type(element) == int 2. float (always true.)

In general, it is recommended to use the function isinstance for type checking.

yechezkel
  • 101
  • 1
  • We haven't learned isinstance yet and we we're told not to use it for now :/ But makes perfect sense, thanks for the answer! – Krio Oct 30 '16 at 06:58