简体   繁体   中英

Returning values from inside a loop

First off, I am a python Noob. What I may be asking could be common knowledge; however, I have had a difficult time figuring it out. I am attempting to create a function which takes a read-in CSV file and changes the types of the elements in the lists. For example, if the list was read in as ['A','B','2'] it would become ['A','B',2] after the function is performed. Below is my code:

def type_setter(x):
    x = list(x)
    for row in x:
        for i in row:
            if i.isdigit() == True:
                i = eval(i)

    return [row for row in x]

The problem I am having is returning the values after the if i.isdigit()==True: part. It seems the values are staying within the loop and not being stored into the list x. Any help is greatly appreciated.

The problem I am having is returning the values after the "if i.isdigit()==True:" part. It seems the values are staying within the loop and not being stored into the list x.

That's because you don't do anything to store them in the list. Just doing i = eval(i) just reassigns the local variable i to a new value.

For example, you could do this:

    for row in x:
        for index, i in enumerate(row):
            if i.isdigit() == True:
                row[index] = eval(i)

Here, we're reassigning the list member row[index] to a new value, which is exactly what you wanted to do.


Some side notes:

It's usually a lot simpler to build a new list than to try to modify one in place.

You should almost never call eval . If you want to turn a digit into an integer, just use int . (For fancier cases, where you have some kind of Python literal, you may want ast.literal_eval . But you never want eval , unless you really want to run arbitrary code.)

And you almost never want to check == True .

Also, [row for row in x] is exactly the same thing as list(x) —which, in this case, is just an extra copy of x for no reason, because you've already turned x into a list.

And if you could find a way to do this in one pass, instead of two, you wouldn't need the x = list(x) at the top.

Putting that all together:

def type_setter(x):
    new_x = []
    for row in x:
        new_row = []
        for i in row:
            if i.isdigit():
                new_row.append(int(i))
            else:
                new_row.append(i)
        new_x.append(new_row)
    return new_x

Or, more concisely:

def type_setter(x):
    return [[int(i) if i.isdigit() else i] for i in row] for row in x]

Although it might be a bit more readable to leave it as two expressions instead of one:

def type_setter(x):
    def intify(i):
        return int(i) if i.isdigit() else i
    return [[intify(i) for i in row] for row in x]

As one last note, in Python, EAFP ("Easier to Ask Forgiveness than Permission", meaning you just try what you want to do, and deal with errors when you can't do it) is often simpler than LBYL ("Look Before You Leap", meaning you check whether you'll be able to do what you want).

And that may be true in this case. For example, do you want to treat -123 as an integer instead of a string? Then i.isdigit() is the wrong test; you need something more complicated. In fact, in that case, the test you really want is "is a string representation of an integer", right? That's a hard test to write without calling int . So just call it:

def type_setter(x):
    def intify(i):
        try:
            return int(i)
        except ValueError:
            return i
    return [[intify(i) for i in row] for row in x]

You can modify the list directly:

def type_setter(x):
    x = list(x)
    for row_num, row in enumerate(x):
        for col_num, i in enumerate(row):
            if i.isdigit() == True:
                x[row_num][col_num] = int(i)

    return x

Also you should not use eval to evaluate any untrusted sources. In cour case you can use int to convert a string to a number.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM