Heim  >  Artikel  >  Backend-Entwicklung  >  python中的赋值,什么时候是传值什么时候是传址?

python中的赋值,什么时候是传值什么时候是传址?

WBOY
WBOYOriginal
2016-06-06 16:24:322478Durchsuche

s = [1, 2, 3]
t = s
t.reverse()
然后s和t都变成了[3, 2, 1]

但是如果s = [1, 2, 3]
t = s[::-1]
只有t是[3, 2, 1] s还是[1, 2, 3]不变的...

所以我比较奇怪,python中的赋值,什么时候是传值什么时候是传址?

回复内容:

Python一切皆为对象。赋值一直都是传址。所有变量都是保存着对象的地址。

首先,分析一下题主所描述的两种情况出现不同的原因。
第一种情况将s赋值给了t,此时s和t指向了同一个对象。所以执行reverse时,对象本身被改变。因为s和t指向同一个对象,所以你无论输出s还是t都是输出同一个已经被reverse的对象。
第二种情况是对s执行了一个slicing的操作。此时本身s[::-1]返回的不是s对象本身,而是一个在内存中根据运算重新生成的对象,所以t得到的是一个s[::-1]生成的新对象的地址。而s还是保留着原来的对象,由于s[::-1]不会改变原来对象的值,所以s的值是不会改变的。

再进一步。

在Python中,即使是整数类型,它也是按照对象来处理的。例如a=1,它并不是将1值赋值给了a,而是将一个整数对象1的地址赋值给了a。由于Python对小整数的特殊处理,凡是在一定范围内的小整数,是统一使用了“小整数对象池”。也就是说所有的小整数,例如1,都是使用对象池里面的同一个对象。但是,小整数对象池是有限的,范围是[-5, 257) 注意左闭右开。所以,超过这个范围的整数,严格来说,是需要生成这样的一个对象的。所以,就会出现下面的情况

<code class="language-python"><span class="o">>>></span> <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">>>></span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">>>></span> <span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">==</span> <span class="nb">id</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="bp">True</span>

<span class="o">>>></span> <span class="n">c</span> <span class="o">=</span> <span class="mi">1000000</span>
<span class="o">>>></span> <span class="n">d</span> <span class="o">=</span> <span class="mi">1000000</span>
<span class="o">>>></span> <span class="nb">id</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">==</span> <span class="nb">id</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="bp">False</span>
</code>
在python中, parameter sent to function 使用的全部是 by object。
也就是,这无法通过by value或者 by reference 来定义。这是python的独到之处。
如果object本身是immutable的,例如一个不是太长的整数,那么你可以看作是传值。因为每一次对这个object赋值,都会创建一个新的object,如下:

a=10

def function1(value):
value=20
print(value)

function1(a)

print(a)
结果是
20
10
虽然传过去的是a这个object,但当function1对a赋值的时候,其实他并没有改变a,而是创建了一个新的object,这个object叫做value了。global当中的a并没有变。

如果object本身是mutable,例如一个list,因为每一次对这个object赋值,都会改变这个object本身。那么就可以看作是传reference。如下:

a=[10,11,12,13]

def function1(value):
value[1:3]=[]
print(value)

function1(a)

print(a)
结果是
[10,13]
[10,13]

。。答到一半,看了下题目好像答非所问了。

题目问的问题其实更简单。
list.reverse 是一个in-place method。也就是说,reverse是在原来object上操作,而不会创造一个新的object。上面t=s,按照python传object的标准,那么就是t=s 是同一个object。.reverse作用在这个object上,那么t,s都变了。他们只是名字而已。

而slicing [::] 这个,会创造一个新的object。所以。自然啦。
最好的办法是deep copy 赋值只是传址,切片的话就是copy值了
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn