Python 为什么这两种形式的迭代产生不同的结果?

Python 为什么这两种形式的迭代产生不同的结果?,python,Python,第一段代码没有实现我需要的东西,而第二段代码实现了 这两段代码之间的区别是什么?因为字符串是不可变的: 值可以更改的对象称为可变对象;对象 值一旦创建就不可更改,称为不可变。(修订) 包含对对象的引用的不可变容器对象的值 可变对象可以在后者的值更改时更改;但是 容器仍然被认为是不可变的,因为 它所包含的对象无法更改。因此,不可变性不是必需的 严格来说,与具有不可更改的值相同,它更微妙。) 对象的易变性由其类型决定;例如, 数字、字符串和元组是不可变的,而字典和 列表是可变的 在第一个示例中,每

第一段代码没有实现我需要的东西,而第二段代码实现了


这两段代码之间的区别是什么?

因为字符串是不可变的:

值可以更改的对象称为可变对象;对象 值一旦创建就不可更改,称为不可变。(修订) 包含对对象的引用的不可变容器对象的值 可变对象可以在后者的值更改时更改;但是 容器仍然被认为是不可变的,因为 它所包含的对象无法更改。因此,不可变性不是必需的 严格来说,与具有不可更改的值相同,它更微妙。) 对象的易变性由其类型决定;例如, 数字、字符串和元组是不可变的,而字典和 列表是可变的

在第一个示例中,每次将附加值连接到一个名为
x
的新变量时,都会创建一个新变量


然而,在第二个示例中,您只是简单地更改了
列表的同一索引处的值。Shorty:在第一个示例中,您没有更改列表值,在第二个示例中,您更改了列表值。

在第一个循环中修改
x
,它实际上是列表项的副本,但不是该项,在第二个示例中,通过索引访问列表项来修改列表项。请参阅以获取有关可变和不可变类型的更多信息

但是,如果要在包含可变类型的列表上应用循环,则项目将由
for
循环修改:

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"

您的第一个循环可以固定为:

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
或者更简洁地说:

for i, x in enumerate(alist):
    if "@gmail.com" not in x:
        alist[i] = x + "@gmail.com"
由于
中的
如果该字符串在字符串中的任何位置将返回true,因此在上述两种情况下首选
而不是x.endswith(@gmail.com”)

当您在代码的第一个版本中执行
x=x+“@gmail.com”
时,您正在创建一个新值,并重新绑定名称
x
,以引用它。这对
alist
没有影响,即使前面的
x
值来自于此

另一方面,如果执行
blist[x]=blist[x]+“@gmail.com”
,则显式修改列表。您正在重新绑定
blist[x]
以引用新值


注意,对于不同的列表内容,您可能已经能够使用“就地”修改使代码的第一个版本工作。但是字符串是不可变的,因此没有就地操作。但是,如果
alist
包含可变项,如
list
s,则类似
x+=[“foo”]
的代码将适当地扩展内部列表。如果对象的类型支持,则
+=
运算符将尝试执行就地添加(通过使用
\uuuuu iadd\uuu
方法)。但是,对于不支持就地操作的类型,它与
x=x+y
相同,这与您遇到的问题相同。

您可以通过使用列表理解来避免此问题:
[x-if'@gmail.com'in x-else'{}@gmail.com'。blist中x的格式(x)
谢谢!你的代码很适合我!我还向您学习了string.format()。再次感谢@我不确定我是否理解这与字符串不可变有什么关系。如果
alist
是一个列表列表,OP的第一个循环仍然不起作用。是的,但OP希望更改
x
的值会反过来更改列表元素,但即使
x
最初是对
alist
元素的引用(通过
for
),它也会在循环中重新初始化。如果
x
是可变的,我们可以使用类似
x.set_value(x+“@gmail.com”)
的东西,但是因为它是不可变的,所以它们不能。好吧,对我来说,这似乎更多地与python迭代器的性质有关,而不是与iterable中对象的可变性有关。不过我知道你是从哪里来的。正如我所解释的,如果
x
是另一个(可变)对象,那么无论Python迭代器的性质如何,这两个循环都可以编写为工作相同。
而不是x.endwith(@gmail.com”)
非常棒!你的理解是错误的。它创建的列表将不包含以
“@gmail.com”
开头的列表项。@pzp:谢谢--已修复
email="@gmail.com"
alist=[x+email if email not in x else x for x in alist]