在Python中,有没有一种方法可以使用foreach样式的构造来更新容器?

在Python中,有没有一种方法可以使用foreach样式的构造来更新容器?,python,list,for-loop,foreach,containers,Python,List,For Loop,Foreach,Containers,我假设Python中的foreach样式构造允许我像在C#中一样更新列表。没有 经过一些调查,我发现foreach样式构造中的Python中使用的变量不是一个引用,而是一个单独的标量变量,因此我无法使用它更新容器。有没有办法使用foreach样式更新容器 下面是一些演示我的问题的代码: inputString = " Type X Widgets , 25, 14.20 , Type Y Widgets , 4 , 1.12 " inputList = inputString.spl

我假设
Python
中的foreach样式构造允许我像在
C#
中一样更新列表。没有


经过一些调查,我发现foreach样式构造中的
Python
中使用的变量不是一个引用,而是一个单独的标量变量,因此我无法使用它更新容器。有没有办法使用foreach样式更新容器

下面是一些演示我的问题的代码:

inputString = "   Type X Widgets  ,  25, 14.20 ,  Type Y Widgets , 4  , 1.12 "
inputList = inputString.split(',')
print(inputList) # Now I need to get rid of whitespace on the ends of each element

# The foreach-style does NOT update inputList
for element in inputList:
    element = element.strip()
    print(element, end=",") # element contains the stripped string as I wanted
print()
print(inputList) # the whitespace on the ends of the elements is still there

# The for-style with subscripts DOES update inputList
for i in range(len(inputList)):
    inputList[i] = inputList[i].strip()
    print(inputList[i], end=",") # inputList[i] contains the stripped string as I wanted
print()
print(inputList) # it finally contains the stripped strings with no whitespace on the ends
以下是上述内容的输出:

['   Type X Widgets  ', '  25', ' 14.20 ', '  Type Y Widgets ', ' 4  ', ' 1.12 ']
Type X Widgets,25,14.20,Type Y Widgets,4,1.12,
['   Type X Widgets  ', '  25', ' 14.20 ', '  Type Y Widgets ', ' 4  ', ' 1.12 ']
Type X Widgets,25,14.20,Type Y Widgets,4,1.12,
['Type X Widgets', '25', '14.20', 'Type Y Widgets', '4', '1.12']
第一个for循环不会更新容器。第二个是。在这个简单的例子中,我必须使用下标并不重要,但我真的希望能够在下标根本不起作用时使用foreach样式来更新更复杂的容器类型


我可以在
C#
中实现这一点,这是一个非常强大的工具。在
Python
中,除了我在第一个循环中尝试的方法之外,是否还可以执行其他操作?(如果是这样的话,我想这将涉及到使用指针。
Python
甚至有指针吗?

也许这不是您想要的,但一个简单的方法是创建一个新列表,如下所示:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
这会将新列表分配给同一个变量,替换旧的变量(在此之后,旧的列表将被垃圾收集)


缺点是,这会使使用的内存量翻倍;完成上述语句后,可以对旧列表进行垃圾收集,但内存使用量仍会急剧增加。

也许这不是您想要的,但一种简单的方法是创建一个新列表,如下所示:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
这会将新列表分配给同一个变量,替换旧的变量(在此之后,旧的列表将被垃圾收集)


缺点是,这会使使用的内存量翻倍;完成上述语句后,可以对旧列表进行垃圾收集,但内存使用率仍将出现峰值。

在这种特定情况下,您不能这样做。这是因为您正在将对象重新指定给一个新的引用

在“foreach”类型的迭代中,如下所示:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
您正在遍历列表中元素本身的对象。但在本例中,它是一个不可变的
str
对象。i、 e.当您尝试分配此行时:

element = element.strip()
您正在使用原始内容的剥离内容中的新对象重新指定元素。因为它是一个新对象,所以它与
inputList
本身没有任何关系

但是,在第二个示例中,您现在正在迭代基于
inputList
的索引列表:

for i in range(len(inputList)):
# range(len(inputList)) -> range(0, 6)
在遍历列表时,请注意,您再次指定了
inputList
的特定索引:

inputList[i] = inputList[i].strip()
这会将一个新对象分配回
inputList[i]
。它不再是列表中曾经的
str
对象

话虽如此,在其他用例中,只要对象是可变的,您正在寻找的“foreach”就可以正常工作。观察以下示例:

lst = [[] for _ in range(5)]
lst
# [[], [], [], [], []]
for i in lst:
    i.append('foo')

lst
# [['foo'], ['foo'], ['foo'], ['foo'], ['foo']]
请注意此处的差异:
i
不是重新分配的,而是由
append()
方法直接更改的。为了进一步证明
i
是符合您期望的直接对象引用,如果我在迭代完成后这样做:

请参见如何添加
lst
的最后一个元素。这是因为
i
仍然保留引用。
id()

如果我像这样编写迭代:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
lst中的i的
:
i=['foo']
lst
# [[], [], [], [], []]
身份证(一)

#61354112在这种特殊情况下,您不能。这是因为您正在将对象重新指定给一个新的引用

在“foreach”类型的迭代中,如下所示:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
您正在遍历列表中元素本身的对象。但在本例中,它是一个不可变的
str
对象。i、 e.当您尝试分配此行时:

element = element.strip()
您正在使用原始内容的剥离内容中的新对象重新指定元素。因为它是一个新对象,所以它与
inputList
本身没有任何关系

但是,在第二个示例中,您现在正在迭代基于
inputList
的索引列表:

for i in range(len(inputList)):
# range(len(inputList)) -> range(0, 6)
在遍历列表时,请注意,您再次指定了
inputList
的特定索引:

inputList[i] = inputList[i].strip()
这会将一个新对象分配回
inputList[i]
。它不再是列表中曾经的
str
对象

话虽如此,在其他用例中,只要对象是可变的,您正在寻找的“foreach”就可以正常工作。观察以下示例:

lst = [[] for _ in range(5)]
lst
# [[], [], [], [], []]
for i in lst:
    i.append('foo')

lst
# [['foo'], ['foo'], ['foo'], ['foo'], ['foo']]
请注意此处的差异:
i
不是重新分配的,而是由
append()
方法直接更改的。为了进一步证明
i
是符合您期望的直接对象引用,如果我在迭代完成后这样做:

请参见如何添加
lst
的最后一个元素。这是因为
i
仍然保留引用。
id()

如果我像这样编写迭代:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
lst中的i的
:
i=['foo']
lst
# [[], [], [], [], []]
身份证(一)

#61354112Hhm。在for循环中,在每次迭代期间,变量(在case元素中)将分配给列表中下一个值(对象)的副本,而不是该值(对象)的引用。(这并不完全正确,但你知道我想说什么)。因此,为了解决您的项目,您可以做如下操作:

inputList = [
    element.strip()
    for element in inputList]
for element in inputList:
for i in lst:
    i = ['foo']

lst
# [[], [], [], [], []]
id(i)
# 61354112 <-- different obj id
id(lst[-1])
# 61353816
for element in inputList:
    inputList[inputList.index(element)] = element.strip()
print(inputList)
请注意,当列表中有相同元素两次时,这将不起作用


希望有帮助

Hhm。在for循环中,在每次迭代期间,您的变量(在