导致Python错误' str '对象不支持项分配的原因是什么
我正在调试一些Python 2.7.3的代码,目的是遍历一个物品列表,并把每个物品转换成字符串:
req_appliances = ['9087000CD', 'Olympus', 185]
for i in range(0, len(req_appliances)):
req_appliances[i] = str(req_appliances[i])
print req_appliances
输出结果如下:
['9087000CD', 'Olympus', '185']
在上面的例子中,我把req_appliances的值设置为一个具体的值,以便测试这个循环。在实际的代码中,req_appliances是一个函数的参数。我在运行时不知道这个参数的类型,但它看起来像是一个标量值的列表。我知道当我调用这个函数时,会出现以下错误信息:
File ".../database.py", line 8277, in get_report_appliance_list
req_appliances[i] = str(req_appliances[i])
TypeError: 'str' object does not support item assignment
我想弄清楚req_appliances这个参数的哪些值会导致这个错误出现。在我看来,所有的值都是标量,并且每个值(即使是不可变的)在赋值时应该都是有效的左侧表达式。我是不是漏掉了什么?这里是代码的上下文,也就是它被定义的函数:
def get_report_appliance_list(self, req_appliances, filter_type=None):
appliances = {}
appliance_list = []
if filter_type != None:
if filter_type not in ('appliances', 'servers'):
raise ValueError("appliance filter_type must be one of 'appliances' or 'servers'")
active_con = self.get_con()
if active_con is None:
raise Exception('No database connections are available.')
con = None
in_expr_items = ''
if req_appliances != None:
# Create a string like '(%s, %s, ...)' to represent
# the 'in' expression items in the SQL.
print(req_appliances)
for i in range(0, len(req_appliances)):
req_appliances[i] = str(req_appliances[i])
in_expr_items += '%s,'
in_expr_items = '(' + in_expr_items[:-1] + ') '
2 个回答
这其实不是对你问题的直接回答,而是一些风格上的建议。如果你经常使用 for i in range(0, len(something))
这种写法,建议你可以用 for i, obj in enumerate(something)
,或者用 map(func, something)
,还有一种更简洁的写法是列表推导式 [func(x) for x in something]
。
另一个需要注意的地方是,在循环中使用字符串的 +=
操作。这种做法不太好,建议你先创建一个数组,然后再把它们合并成一个字符串。这样做还可以避免像 [-1]
这种操作来去掉多余的逗号。
关于你的代码,其实可以简化很多:
def get_report_appliance_list(self, req_appliances, filter_type=None):
appliances = {}
appliance_list = []
if filter_type not in (None, 'appliances', 'servers'):
raise ValueError("appliance filter_type must be one of 'appliances' or 'servers'")
active_con = self.get_con()
if active_con is None:
raise Exception('No database connections are available.')
# Create a string like '(%s, %s, ...)' to represent
# the 'in' expression items in the SQL.
in_expr_items = ','.join(['%s'] * len(req_appliances)
req_appliances = map(str, req_appliances)
...
除此之外,我建议让 get_con()
抛出异常,这样你就不需要在代码中检查 None
了。
在Python中,str
(字符串)就像一种可以逐个访问的序列类型(你可以一个一个地遍历它),但是字符串是不可变的,也就是说你不能给它的任何位置赋新值。
我猜这里发生的事情是,你在尝试运行代码时,req_appliances
是一个str
对象。
我想到了两种解决方法:
第一种,先检查一下它是不是str
,再进行遍历:
if isinstance(req_appliances, basestring):
return req_appliances
第二种,你可以在尝试赋值之前,检查每个项目是否已经是字符串。
req_appliances = ['9087000CD', 'Olympus', 185]
for i in range(0, len(req_appliances)):
if req_appliances[i] != str(req_appliances[i]):
req_appliances[i] = str(req_appliances[i])
print req_appliances
在这里,我实际上是在检查这个成员是否等于它的字符串表示。 当你遍历字符串时,这个条件是成立的。
>>> a = 'a'
>>> a[0] == str(a[0])
True