Python修改类范围外的列表
我试图在Python中调用在类作用域之外定义的函数,它修改传递的值,而不引用传递的变量,但类作用域中的原始变量会被修改 我已经广泛地使用python来编写脚本,但实际上并没有对类做太多工作。我看了这篇文章,它解释了很多,但并没有真正谈论它。这个变量肯定超出了范围,它是如何变异的Python修改类范围外的列表,python,Python,我试图在Python中调用在类作用域之外定义的函数,它修改传递的值,而不引用传递的变量,但类作用域中的原始变量会被修改 我已经广泛地使用python来编写脚本,但实际上并没有对类做太多工作。我看了这篇文章,它解释了很多,但并没有真正谈论它。这个变量肯定超出了范围,它是如何变异的 def doSomethingOutOfScope(arr): spv = arr[0] arr[0] = 'S' class Solution: def doSomethingInScope
def doSomethingOutOfScope(arr):
spv = arr[0]
arr[0] = 'S'
class Solution:
def doSomethingInScope(self, passed_arr):
print(passed_arr) # prints [0, 1, 2]
doSomethingOutOfScope(passed_arr) # passed_arr shouldn't get modified
print(passed_arr) # prints ['S', 1, 2] - Why ?
s = Solution()
s.doSomethingInScope([0, 1, 2])
Python列表实际上是可变的,并且是通过引用传递的Python列表实际上是可变的,并且是通过引用传递的在Python中,一切都是一个对象,每个对象都是通过引用传递的。因此,基本上,除了重新分配外,您直接对传递的对象所做的任何更改都会实时反映在对象本身上。需要注意的关键是对象的可变性,即通过初始赋值,对象是否是可变的 例如,
str
和int
对象是不可变的。注意,str
和int
下没有任何方法可以直接更改对象:
s = 'foo' # str type
s.upper() # FOO
print(s)
# foo
请注意str.upper()
方法如何不改变s
本身。为了使s
成为“FOO”,您需要重新分配s
:
s = s.upper()
print(s)
# FOO
但是,通过重新分配对象(obj=…
),它会更改对象引用,其中id
现在将不同。因此,如果像这样传递str
:
def func(string):
string = string.upper()
func(s)
s
将保持不变,因为在重新分配string=…
时,string
将不再具有与s
相同的对象引用
但是,对于可变对象,只要不重新分配,对象本身就会进行更改:
l = list('abcde')
def func(lst, value):
lst.append(value)
# no reassignment
func(l, 'f')
print(l)
# ['a', 'b', 'c', 'd', 'e', 'f']
这是因为对象引用(id(l)
)在函数中保持不变
综上所述,在您的情况下,如果您想对对象执行某些操作,但不想对其进行变异,您可以传递对象的副本(该副本将具有不同的
id
),或者在本地范围内创建传递对象的副本:
# pass a copy of the object:
def func(lst):
lst.append('x')
return lst
func(lst[:])
# OR, create a local object
def out_of_scope(lst):
temp_lst = lst[:]
temp_lst.append('x')
return temp_lst
在这种特殊情况下,[:]
将列表的完整片段作为另一个对象返回
关于更多信息,这里有一个.在Python中,一切都是一个对象,每个对象都在引用中传递。因此,基本上,除了重新分配外,您直接对传递的对象所做的任何更改都会实时反映在对象本身上。需要注意的关键是对象的可变性,即通过初始赋值,对象是否是可变的
例如,str
和int
对象是不可变的。注意,str
和int
下没有任何方法可以直接更改对象:
s = 'foo' # str type
s.upper() # FOO
print(s)
# foo
请注意str.upper()
方法如何不改变s
本身。为了使s
成为“FOO”,您需要重新分配s
:
s = s.upper()
print(s)
# FOO
但是,通过重新分配对象(obj=…
),它会更改对象引用,其中id
现在将不同。因此,如果像这样传递str
:
def func(string):
string = string.upper()
func(s)
s
将保持不变,因为在重新分配string=…
时,string
将不再具有与s
相同的对象引用
但是,对于可变对象,只要不重新分配,对象本身就会进行更改:
l = list('abcde')
def func(lst, value):
lst.append(value)
# no reassignment
func(l, 'f')
print(l)
# ['a', 'b', 'c', 'd', 'e', 'f']
这是因为对象引用(id(l)
)在函数中保持不变
综上所述,在您的情况下,如果您想对对象执行某些操作,但不想对其进行变异,您可以传递对象的副本(该副本将具有不同的id
),或者在本地范围内创建传递对象的副本:
# pass a copy of the object:
def func(lst):
lst.append('x')
return lst
func(lst[:])
# OR, create a local object
def out_of_scope(lst):
temp_lst = lst[:]
temp_lst.append('x')
return temp_lst
在这种特殊情况下,[:]
将列表的完整片段作为另一个对象返回
关于更多信息,这里有一个例子