函数更改在Python中列出值而不是变量值

函数更改在Python中列出值而不是变量值,python,list,function,variables,nested-lists,Python,List,Function,Variables,Nested Lists,让我们看一个简单的代码: y = [1,2,3] def plusOne(y): for x in range(len(y)): y[x] += 1 return y print plusOne(y), y a = 2 def plusOne2(a): a += 1 return a print plusOne2(a), a “y”的值更改,但“a”的值保持不变。我已经了解到这是因为一个是可变的,而另一个是不可变的。但是如何更改代码,

让我们看一个简单的代码:

y = [1,2,3]

def plusOne(y):
    for x in range(len(y)):
        y[x] += 1
    return y

print plusOne(y), y


a = 2

def plusOne2(a):
    a += 1
    return a

print plusOne2(a), a
“y”的值更改,但“a”的值保持不变。我已经了解到这是因为一个是可变的,而另一个是不可变的。但是如何更改代码,使函数不更改列表

例如,要执行类似操作(为了简单起见,使用伪代码):

编辑:对不起,我还有一个关于嵌套列表的问题。请参阅此代码:

def change(y):
    yN = y[:]
    for i in range(len(yN)):
        if yN[i][0] == 1:
            yN[i][0] = 0
        else:
            yN[i][0] = 1
    return yN

data1 = [[1],[1],[0],[0]]
data2 = change(data1)

在这里它不起作用。为什么?再次:如何避免这个问题?我理解它为什么不起作用:yN=y[:]将y的值复制到yN,但这些值也是列表,因此对于列表中的每个列表,操作都必须加倍。如何使用嵌套列表执行此操作?

创建列表的副本。使用
testList=inputList[:]
。参见代码

>>> def plusOne(y):
        newY = y[:]
        for x in range(len(newY)):
            newY[x] += 1
        return newY

>>> y = [1, 2, 3]
>>> print plusOne(y), y
[2, 3, 4] [1, 2, 3]
或者,您可以在函数中创建一个新列表

>>> def plusOne(y):
        newList = []
        for elem in y:
            newList.append(elem+1)
        return newList
你也可以像其他人指出的那样使用理解

>>> def plusOne(y):
        return [elem+1 for elem in y]

您可以使用切片表示法传递列表的副本:

print plusOne(y[:]), y
或者更好的方法是在函数本身中创建list的副本,这样调用者就不必担心可能的修改:

def plusOne(y):
    y_copy = y[:]
然后改为使用
y\u copy


或者正如@abarnet在评论中指出的那样,您可以修改函数以使用
列表理解
,这将创建一个新的列表:

return [x + 1 for x in y]

Python变量包含指向对象的指针或引用。所有值(甚至整数)都是对象,赋值会更改变量以指向不同的对象。它不会在变量中存储新值,而是更改变量以引用或指向其他对象。出于这个原因,许多人说Python没有“变量”,它有“名称”,并且
=
操作没有“为变量赋值”,而是“将名称绑定到对象”

plusOne
中,您正在修改(或“变异”)
y
的内容,但决不更改
y
本身所指的内容。它始终指向同一个列表,即您传递给函数的列表。全局变量
y
和局部变量
y
引用相同的列表,因此使用任一变量都可以看到更改。由于您更改了传入的对象的内容,因此实际上没有理由返回
y
(事实上,返回
None
是Python本身对此类“就地”修改列表的操作所做的操作——值由创建新对象而不是修改现有对象的操作返回)

plusOne2
中,您正在更改局部变量
a
以引用不同的整数对象
3
。(“将名称
a
绑定到对象
3
)全局变量
a
不会因此而改变,而是继续指向
2


如果您不想更改传入的列表,请复制并更改该列表。然后,您的函数应该返回新列表,因为它是创建新对象的操作之一,如果您不返回,新对象将丢失。例如,您可以在函数的第一行执行此操作:
x=x[:]
(正如其他人所指出的)。或者,如果以任何一种方式调用函数都可能有用,如果调用方希望复制,您可以让调用方传入
x[:]

只需创建一个包含所需值的新列表,然后返回该列表即可

def plus_one(sequence):
    return [el + 1 for el in sequence]

正如其他人所指出的,如果您不想修改原始列表,您应该使用
newlist=original[:]
newlist=list(original)
来复制列表

def plusOne(y):
    y2 = list(y)  # copy the list over, y2 = y[:] also works
    for i, _ in enumerate(y2):
        y2[i] += 1
    return y2
但是,您可以通过列表获得所需的输出

def plusOne(y):
    return [i+1 for i in y]

这将迭代
y
中的值,并通过向每个值添加一个来创建一个新的列表,以回答您编辑的问题:


复制嵌套数据结构称为深度复制。要在Python中执行此操作,请在模块中使用
deepcopy()

您可以通过生成一个函数并通过map函数调用此函数来完成此操作, map函数将调用add函数并给它赋值,然后它将按如下方式打印新值:

def add(x):
    return x+x
print(list(map(add,[1,2,3])))
或者您可以使用(*range)函数,这样做非常简单,例如:

print ([i+i for i in [*range (1,10)]])

或者,更好的做法是重写代码,以便动态生成副本:
y=[x+1代表y中的x]
@abarnert。右:)谢谢,编辑了答案。:)这对新手来说有点困惑(因为通过Python学习编程的人都不知道指针是什么),对其他人来说有点误导(因为变量不是指针,它们是名称,问题是绑定与变异,而不是指针变量与普通变量)。我做了一些修改来澄清其中的一些问题。我希望如此。一般来说,避免突变引起混乱的最简单方法就是避免突变。当这不合适时,答案是复制并变异。真的没有其他选择了。既然你接受了@kindall的答案,也许你会觉得有用。在我看来,它解释得更详细更清晰。哇,谢谢你的快速回复!!我尝试了newY=y,但它不起作用,而应该是简单的newY=y[:]。
newY=y
只是创建了对它的另一个引用,而
newY=y[:]
创建了一个新列表。是的,现在我明白了,一切都清楚了!谢谢
print ([i+i for i in [*range (1,10)]])