【问题标题】:Multiply every element of a list by a number将列表的每个元素乘以一个数字
【发布时间】:2016-05-23 04:44:37
【问题描述】:

我想将列表的所有元素乘以一个数字。我知道其他方法,但我想知道为什么这不起作用?我得到了与输出完全相同的列表。

lst = eval(input('enter a list'))
for num in lst:
     num = num * 2
print(lst)

【问题讨论】:

  • 您只是在更新循环变量,而不是列表的内容...
  • 您是否需要更改lst 本身,或者新列表可以吗?
  • 致所有回答者:我认为 OP 知道如何做到这一点,而这个问题是关于 为什么这不起作用 而不是 我怎样才能得到这个作品
  • 这个问题有两个正确的答案,0 票@KevinGuan

标签: python


【解决方案1】:

它不起作用,因为您在列表上使用for 循环并定义/更改num 全局变量,而不是lst 列表中的元素。

例如:

>>> l = [1, 5, 8]
>>> for num in l:
...     num *= 2
...     
... 
>>> num
16
>>> l
[1, 5, 8]

在这种情况下,在第一个循环中,num1l 中的第一个元素),并且肯定 1 * 2 给出 2

然后,num 变为 5,因为 5 是列表中的第二个元素。在num * 2之后,num变成10

在第二个for 循环中,它变为8 * 216。它不会再次更改,因为 for 循环已结束。

但是,您在此循环期间没有更改列表的任何内容。因为for获取列表中的元素,并且把它放到一个临时变量中

当您在 for 循环中更改 临时变量 时,您并没有更改列表中的任何内容。

【讨论】:

    【解决方案2】:

    好吧,既然你写了 “我知道其他方法可以做到,但我想知道为什么这不起作用?”,这是你的答案:你只是在修改临时循环变量num,而不是列表本身。试试这个:

    for i, num in enumerate(lst):
         lst[i] = lst[i] * 2
    

    【讨论】:

    • 不知道为什么 enumerate 会被使用,而 range(len(lst)) 只会遍历索引。有什么原因吗?
    • 否,但这是一个通用解决方案,适用于您还需要变量 num 时。例如,你也可以写lst[i] = num * 2
    【解决方案3】:

    你没有改变lst的元素,这样做:

    for num in range(len(lst)):
        lst[num] *= 2
    

    【讨论】:

      【解决方案4】:

      两个简洁的表达方式:

      In [360]: lst=list(range(10))
      

      就地改变:

      In [361]: for i,v in enumerate(lst):
         .....:     lst[i]=v*2
         .....:     
      In [362]: lst
      Out[362]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
      

      生成一个新列表:

      In [363]: [v*2 for v in lst]
      Out[363]: [0, 4, 8, 12, 16, 20, 24, 28, 32, 36]
      

      对于输入,我更喜欢显式拆分和转换字符串:

      In [365]: lst = [int(x) for x in input().split()]
      10 11 0 1 2 
      In [366]: lst
      Out[366]: [10, 11, 0, 1, 2]
      

      【讨论】:

        【解决方案5】:
        lst=eval(input('enter a list'))
        lst=list(map(lambda num:num*2,lst))
        print (lst)
        

        你需要更新 lst。

        【讨论】:

        • 在 Python 3.X 中,map(...) 将返回一个需要显式转换为列表的 map 对象。
        • 感谢@vks Map 的解决方案使其非常简洁,将阅读它。
        • @vks:我没有投反对票,但可能是因为......请查看问题下方的评论和我的答案。顺便说一句,map列表理解 慢,也请检查Anton Protopopov's answer
        【解决方案6】:

        出于安全考虑,最好使用ast.literal_eval 然后使用eval。你可以阅读它here。你可以用list comprehension解决这个问题:

        import ast
        lst = ast.literal_eval(input('enter a list'))
        lst = [num*2 for num in lst]
        print(lst)
        

        列表推导maplambda 更快。 时间

        lst = list(range(1000))
        
        In [56]: %timeit list(map(lambda num:num*2,lst))
        10000 loops, best of 3: 169 us per loop
        
        In [57]: %timeit [num*2 for num in lst]
        10000 loops, best of 3: 80.5 us per loop
        

        【讨论】:

          【解决方案7】:

          正如其他人指出的那样,正确的方法是对列表进行索引:

          myList = range(5)
          for i in range(len(myList)):
              myList[i] *= 2
          print myList #[0,2,4,..]
          

          关于通过作业的一点点

          使用for num in list 表示法的循环不会修改列表。因为循环变量 num 在循环的每次迭代中都采用 int 类型的值,因为 int 在 python 中是不可变的(即它的值不能更改),num 获取整数值的副本。

          当列表中的对象是可变的并且通过引用传递时,这会发生变化。考虑以下几点:

          class X: 
              def __init__(self):
                   self.val = 1
          
          myList = [X() for i in range(5)]
          print [element.val for element in myList] #1,1,1,1,1
          
          for el in myList:
              el.val = 2
          
          print [element.val for element in myList] #2,2,2,2,2 
          

          现在,由于 myList 包含一个可变的 X 对象列表,循环变量 el 有一个 reference 复制到其中。引用指向内存中与原始 myList 中的引用指向相同的对象。所以当你使用循环变量改变对象时,原来myList中引用的对象也会改变。

          Pass By Reference 对此进行了更深入的讨论。

          【讨论】:

          • 除了可变之外,你还必须改变,你的el.val = 2 确实做到了;为了完整起见,您可以提及 el = 2不会更新列表元素(因为您不再变异,而是替换)。
          猜你喜欢
          • 2016-05-12
          • 2023-03-19
          • 1970-01-01
          • 2015-08-15
          • 2019-10-15
          • 2012-09-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多