alist = ['1', '2', '3']
blist = alist[:]
for x in alist:
if not "@gmail.com" in alist:
x = x + "@gmail.com"
for x in range(len(blist)):
if not "@gmail.com" in blist[x]:
blist[x] = blist[x] + "@gmail.com"
第一个代码块没有实现我需要的东西,但是第二个代码块没有实现。
这两个代码块之间有什么区别?
答案 0 :(得分:2)
Shorty:在第一个示例中,您没有改变列表值,在第二个示例中,这样做。
在第一个循环中,您修改了x
,它实际上是列表项的副本,但不是该项,在第二个示例中,您通过索引访问它来修改列表项。请参阅Immutable vs Mutable types以获取有关可变和不可变类型的更多信息
但是,如果要在列表中应用包含可变类型的循环,则for
循环将修改这些项:
alist = [['1'], ['2'], ['3']]
blist = [['1'], ['2'], ['3']]
for x in alist:
x.append("@gmail.com")
print alist
for x in range(len(blist)):
blist[x].append("@gmail.com")
print blist
答案 1 :(得分:2)
当您在代码的第一个版本中执行x = x + "@gmail.com"
时,您将创建一个新值并重新绑定名称x
以引用它。这对alist
没有影响,即使这是前一个x
值的来源。
另一方面,当您执行blist[x] = blist[x] + "@gmail.com"
时,您将明确修改列表。您正在重新绑定blist[x]
以引用新值。
请注意,对于不同的列表内容,您可能已经能够使用“就地”修改使代码的第一个版本工作。字符串是不可变的,因此没有就地操作。但是,如果alist
包含list
等可变项,则x += ["foo"]
之类的代码会扩展内部列表。如果对象的类型支持(+=
方法),__iadd__
运算符将尝试进行就地添加。但是对于不支持inplace操作的类型,它与x = x + y
相同,它会遇到与您遇到的相同的问题。
答案 2 :(得分:1)
你的拳头循环可以固定为:
for i, x in enumerate(alist):
if "@gmail.com" not in x:
alist[i] = x + "@gmail.com"
或者,更简洁:
email="@gmail.com"
alist=[x+email if email not in x else x for x in alist]
如果该字符串在字符串中的任何位置,in
将返回true,则在上述两种情况下都优先使用not x.endswith("@gmail.com")
。
答案 3 :(得分:0)
因为字符串是不可变的:
https://docs.python.org/2/reference/datamodel.html
值可以改变的对象被认为是可变的;对象的 一旦创建它们,值就不可更改,称为不可变。 (该 包含对a的引用的不可变容器对象的值 当后者的值改变时,可变对象可以改变;然而 容器仍然被认为是不可变的,因为收集了 它包含的对象无法更改。所以,不变性不是 与具有不可改变的值严格相同,它更加微妙。) 对象的可变性由其类型决定;例如, 数字,字符串和元组是不可变的,而词典和 列表是可变的。
在第一个示例中,每次将其他值连接到它时,您将创建一个名为x
的 new 变量。
我是第二个例子,但您只需更改list
的相同索引处的值。