简体   繁体   English

从循环内返回值

[英]Returning values from inside a loop

First off, I am a python Noob. 首先,我是一个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. 我正在尝试创建一个函数,该函数接收读入的CSV文件并更改列表中元素的类型。 For example, if the list was read in as ['A','B','2'] it would become ['A','B',2] after the function is performed. 例如,如果列表被读作['A','B','2'] ,则在执行该函数后它将变为['A','B',2] 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. 我遇到的问题是在if i.isdigit()==True: part之后返回值。 It seems the values are staying within the loop and not being stored into the list x. 似乎值保持在循环内并且不存储到列表x中。 Any help is greatly appreciated. 任何帮助是极大的赞赏。

The problem I am having is returning the values after the "if i.isdigit()==True:" part. 我遇到的问题是在“if i.isdigit()== True:”部分之后返回值。 It seems the values are staying within the loop and not being stored into the list x. 似乎值保持在循环内并且不存储到列表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. 只是做i = eval(i)只是将局部变量i重新分配给一个新值。

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. 在这里,我们将列表成员row[index]重新分配给一个新值,这正是您想要做的。


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 . 你应该几乎从不打电话给eval If you want to turn a digit into an integer, just use int . 如果要将数字转换为整数,只需使用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.) (对于更高级的情况,你有某种Python文字,你可能需要ast.literal_eval 。但你永远不会想要eval ,除非你真的想要运行任意代码。)

And you almost never want to check == True . 你几乎不想检查== 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. 此外, [row for row in x]list(x)完全相同 - 在这种情况下,它只是x的额外副本,因为您已经将x转换为列表。

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. 如果你能找到一种方法来实现这一点,而不是两个,你不需要在顶部的x = list(x)

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). 最后一点,在Python中, EAFP (“更容易请求宽恕而非权限”,意味着你只是尝试你想做的事情,并在你不能做的时候处理错误)通常比LBYL更简单(“Look Before”你跳了“,意味着你检查你是否能够做你想做的事情。

And that may be true in this case. 在这种情况下可能也是如此。 For example, do you want to treat -123 as an integer instead of a string? 例如,您想将-123视为整数而不是字符串吗? Then i.isdigit() is the wrong test; 然后i.isdigit()是错误的测试; 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 . 这是一个很难在不调用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. 此外,你应该使用eval评估任何不受信任来源。 In cour case you can use int to convert a string to a number. 在cour情况下,您可以使用int将字符串转换为数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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