如何在python中替换对象

时间:2012-02-29 00:30:03

标签: python

给出以下示例代码:

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]

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

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

7 个答案:

答案 0 :(得分:7)

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

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

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

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

答案 1 :(得分:4)

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

类似的东西:

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的{{3或者他对此comment的解释。

答案 2 :(得分:3)

正如您撰写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,它可以非常清楚地说明你在做什么。

答案 3 :(得分:2)

尝试python列表理解。这是pythonistas的最爱!

[myfunc(x) for x in mylist]

使用mylist =作为前缀,用新的列表覆盖旧列表。

答案 4 :(得分:1)

返回并阅读哪些数据类型。

  1. 你的功能从未返回任何内容(了解范围)
  2. 您向该函数发送了一个列表,而不是单个项目(数据类型)
  3. 代码:

    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]

答案 5 :(得分:1)

你不能改变数字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]

答案 6 :(得分:1)

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

>>> 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]