0

首先,我是一个python Noob。我可能要问的可能是常识;但是,我很难弄清楚。我正在尝试创建一个函数,该函数采用读入的 CSV 文件并更改列表中元素的类型。例如,如果列表被读入,['A','B','2']它将['A','B',2]在函数执行后变为。下面是我的代码:

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]

我遇到的问题是在if i.isdigit()==True:零件之后返回值。这些值似乎停留在循环内,而不是存储到列表 x 中。任何帮助是极大的赞赏。

4

2 回答 2

2

我遇到的问题是在“if i.isdigit()==True:”部分之后返回值。这些值似乎停留在循环内,而不是存储到列表 x 中。

那是因为你没有做任何事情来将它们存储在列表中。只是i = eval(i)将局部变量重新分配i给一个新值。

例如,您可以这样做:

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

在这里,我们将列表成员重新分配row[index]给一个新值,这正是您想要做的。


一些旁注:

建立一个新列表通常比尝试修改一个列表要简单得多。

你几乎不应该打电话给eval. 如果要将数字转换为整数,只需使用int. (对于更奇特的情况,如果你有某种 Python 文字,你可能想要ast.literal_eval。但你永远不想要eval,除非你真的想运行任意代码。)

而且您几乎从不想检查== True

此外,与 —[row for row in x]完全相同,在这种情况下,它只是无缘无故list(x)的额外副本,因为您已经变成了一个列表。xx

如果你能找到一种方法来一次完成,而不是两次,你就不需要x = list(x)顶部的了。

把所有这些放在一起:

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

或者,更简洁地说:

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

尽管将其保留为两个表达式而不是一个表达式可能更具可读性:

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]

最后要注意的是,在 Python 中,EAFP(“比许可更容易请求宽恕”,意味着您只需尝试您想做的事情,并在无法做到时处理错误)通常比LBYL(“先看You Leap”,意思是你检查你是否能够做你想做的事)。

在这种情况下,这可能是真的。例如,您想将-123其视为整数而不是字符串吗?然后i.isdigit()是错误的测试;你需要更复杂的东西。实际上,在那种情况下,您真正​​想要的测试是“是整数的字符串表示形式”,对吗?这是一个很难编写而不调用的测试int。所以只需调用它:

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]
于 2013-09-17T19:23:53.700 回答
0

可以直接修改列表:

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

此外,您不应该使用eval评估任何不受信任的来源。在这种情况下,您可以使用int将字符串转换为数字。

于 2013-09-17T19:22:43.720 回答