【问题标题】:How to replace an object in python如何在python中替换对象
【发布时间】:2012-03-18 12:23:03
【问题描述】:

给出以下示例代码:

def myfunc(item):
  if item == 2:
    item = 1

mylist = [1,2,3]
for i in mylist:
  myfunc(i)
print(mylist) # output is [1, 2, 3]
# desired output is [1, 1, 3]

我想要一个为列表的部分或全部元素调用的函数。这个函数应该能够改变这些元素。

这个问题最干净的解决方案是什么?

【问题讨论】:

  • 你在哪个版本的 Python 上? 2个还是3个?

标签: python


【解决方案1】:

如果您不需要就地修改列表,您可以使用新值创建一个新列表。为此,您的函数应该简单地返回新值:

def myfunc(item):
    if item == 2:
        return 1
    return item

然后您可以使用map() 或列表推导来构造新列表:

mylist = [1, 2, 3]
print map(myfunc, mylist)

【讨论】:

  • 虽然我的目标是就地编辑,但我喜欢你的 map() 方法。如果没有人想出更好的东西,我会用这个:)
【解决方案2】:

回去看看什么数据类型是什么。

  1. 您的函数从未返回任何内容(了解作用域)
  2. 您向函数(数据类型)发送了一个列表,而不是单个项目

代码:

def myfunc(itemlist):
    for i,item in enumerate(itemlist):
        if item == 2:
            itemlist[i] = 1
    return itemlist

mylist = [1,2,3]
mylist = myfunc(mylist)
print(mylist)

输出是[1, 1, 3]
所需的输出是[1, 1, 3]

【讨论】:

  • 1.我知道范围。我的目标是对列表进行就地编辑。我还想让复杂性远离myfunc(),因为我希望拥有多个这样的功能,并且不想重复代码。 2.oops,这实际上是一个错字。对不起
【解决方案3】:

如果您想就地修改您的列表,您需要使用其索引

类似:

for i,elm in enumerate(mylist):
    mylist[i] = myfunc(elm)

myfunc 看起来像:

def myfunc(item):
    if item == 2:
        return 1
    else:
        return item

有了这个函数,你实际上根本不需要函数,但我希望你明白我的意思:)


扩展一点 Sven 的评论,你可以使用 list-slicing + map():

mylist[:] = map(myfunc, mylist)

我实际上更喜欢这个而不是使用enumerate()。而且由于您似乎使用的是 Python 3,因此 甚至不会构建临时列表

生成器表达式也可以!我不会在一些真正的代码中使用它,因为对我来说看起来不太可读,但这可能是一个有趣的例子:

>>> mylist = [0, 1, 2, 3, 4]
>>> mylist[:] = (x == 2 and 1 or x for x in mylist)
>>> mylist
[0, 1, 1, 3, 4]

编辑: 我对不构建临时列表(对于map()generator-expressions)的看法结果是错误的:请参阅Sven 的comment 或他的解释这个other answer

【讨论】:

  • 使用索引就地修改列表并不是绝对必要的——mylist[:] = map(myfunc, mylist) 也可以。 (不过,它会临时创建一个新列表。)
  • @SvenMarnach:使用enumerate() 不是必须的,但mylist[:] 在某种程度上可以使用mylist 索引,你不觉得吗?
  • @Sven:现在我想起来 OP 似乎在 Python 3 上,所以 map() 甚至不会建立临时列表 :) 我真的很喜欢这个 map() 解决方案。
  • 即使在 Python 3 上,它也会以某种方式构建一个临时列表,至少在使用 CPython 时是这样。这只能通过检查 CPython 源代码才能看到——请参阅Python 2.x answer,它仍然对 Python 3.x 有效。
  • @Sven:我从没想到过,谢谢!我编辑了我的答案。
【解决方案4】:

试试 python 列表推导。这是pythonistas的最爱!

[myfunc(x) for x in mylist]

添加mylist = 以用新列表覆盖旧列表。

【讨论】:

  • 在我看来,这通常比 OP 试图做的事情更好,但这不是 OP 问题的答案,即关于修改列表的问题..
  • 根据 OP 对 Sven 的回答所做的评论,OP 愿意牺牲就地修改。
【解决方案5】:

正如您所写的 myfunc,处理单个项目时,它无法修改列表。这是一件好事

myfunc 接收绑定到某个值的名称 item。您可以将名称 item 重新绑定到一个新值,但这当然不会影响到相同值的任何其他绑定。所有列表都是绑定到值的有序序列,因此要更改它包含的内容,您必须将列表中的一些索引重新绑定到新值(或更改值本身,但数字不能更改;没有将数字 1 更改为数字 2 的方法,您只能将引用数字 1 的内容重新绑定为引用数字 2)。没有引用列表,myfunc 无法更改列表中的绑定。

但是myfunc 不应该关心这个列表。它适用于项目,它不关心您是从列表或字典中获取这些项目,还是从文件中读取它们,或其他任何东西。这就是我所说的 myfunc 无法修改您的列表的好处;否则,您必须针对您的项目可能出现的每个不同上下文重写 myfunc

相反,只需让 myfunc 返回新值:

def myfunc(item):
  if item == 2:
    item = 1
  return item

现在调用 myfunc 的代码可以做你想做的事了。此代码知道项目是从列表中获取的,并且您正试图通过将每个项目替换为 myfunc 对其所做的任何事情来就地转换列表。所以这是你应该实现这个意图的地方;试图将其推入myfunc不是使复杂性远离myfunc 的方法。

mylist = [1,2,3]
for idx, item in enumerate(mylist):
    mylist[idx] = myfunc(item)

如果你发现你一直在为许多不同的函数重复这种模式,你可以把它抽象成另一个函数:

def inplace_map(items, func):
    for i, item in enumerate(items):
        items[i] = func(item)

现在您已经定义了转换逻辑一次,以及每个不同的项目转换一次(并且您可以在列表转换以外的其他上下文中重复使用项目转换函数),对于任何想要通过函数就地转换列表中的项目的给定位置,您只需调用inplace_map,它非常清楚地说明了您在做什么。

【讨论】:

    【解决方案6】:

    您无法更改数字 2 - 它是不可变的,因此它将永远是数字 2。

    对于就地编辑,您真正想要的是更改对象 mylist 本身,而不是更改元素,为此,您需要将对 mylist 的引用传递到您的函数中.

    def myfunc(mylist, myindex):
      if mylist[myindex] == 2:
        mylist[myindex] = 1
    

    或者,最简洁的解决方案就是使用列表推导构建一个新列表。

    def myfunc(item):
      if item == 2:
        item = 1
      return item
    
    mynewlist = [myfunc(i) for i in mylist]
    

    【讨论】:

      【解决方案7】:

      您可以使用元素的索引来修改列表:

      >>> l=[1,2,3]
      >>> def f(l):
      ...    for i,v in enumerate(l):
      ...       if v==2: l[i]=1
      ... 
      >>> f(l)
      >>> l
      [1, 1, 3]
      

      如果你的地方 mod 有多个元素,请在 LH 上使用切片:

      >>> def f2(l):
      ...    for i,v in enumerate(l):
      ...       if v==3: l[:]=[-1,-2,-3]
      ... 
      >>> f2(l)
      >>> l
      [-1, -2, -3]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-30
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多