首先,我是一个蟒蛇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中。任何帮助是极大的赞赏。
答案 0 :(得分: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)
完全相同 - 在这种情况下,它只是x
的额外副本,因为您已经转过{ {1}}到列表中。
如果你能找到一种方法,一次通过而不是两次,你就不需要顶部的x
。
把所有这些放在一起:
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]
最后一点,在Python中,EAFP(“更容易请求宽恕而非权限”,意味着你只是尝试你想做的事情,并在你不能做的时候处理错误)经常比LBYL更简单(“Look Before You Leap”,意思是检查你是否能够做你想做的事。)
在这种情况下可能也是如此。例如,您想将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]
视为整数而不是字符串吗?然后-123
是错误的测试;你需要更复杂的东西。事实上,在这种情况下,你真正想要的测试是“是一个整数的字符串表示”,对吧?这是一个难以在不调用i.isdigit()
的情况下编写的测试。所以只需称呼它:
int
答案 1 :(得分: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
来评估任何不受信任的来源。在cour情况下,您可以使用int
将字符串转换为数字。