Home  >  Article  >  Backend Development  >  关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?

关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?

WBOY
WBOYOriginal
2016-06-06 16:22:351470browse

为什么我觉得好不方便啊......
比如如下的代码:

x=[1,2,3,4]
y=x
y[0]=4
print x
>> x = [4 2 3 4]

回复内容:

挺方便的
object.h
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?

而Python中一切皆来源于此,而这两个宏定义为:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?其实可发现PyObject_VAR_HEAD也只是PyObject_HEAD加上一个ob_size,于是Python中,每一个对象都拥有相同的对象头部,于是我们只需要用一个PyObject *就可以引用任意的一个对象,而不论该对象实际是一个什么对象,所以,当内存中存在某个Python对象时,该对象的开始的几个字节的含义一定会符合我们的预期,即PyObject_HEAD。而PyObject_HEAD宏定义中的_PyObject_HEAD_EXTRA其实只是指向_object的一个双向链表,
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?而ob_refcnt则是引用计数的计数器,而struct _typeobject *obtype则是类型,表示对象类型的类型对象:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?
通过PyObject_VAR_HEAD可以发现类型其实也是一个对象(一切皆对象),而类型对象的类型则是类型对象所关联的类型:PyType_Type:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?而即使如简单的int也是来填满这里的东西:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思? 关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?于是,即使是int也是对象
所以即使你使用
i = 47
j = 47
也是对47的一个引用,而
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?
通过id,可以看出其在内存引用位置相同,而为什么相同?因为为了减少频繁调用开销,使用了small int对象池的技术:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?于是只要超过257(包括257),则变了:
关于python中“赋值就是建立一个对象的引用”,大家怎么看?Python一切皆为对象又是什么意思?所以, m,n虽然都是对258对象的引用,却是不同的内存地址了.

剩下的你就可以继续按照这条路线探寻Python的机制了,而你的问题也基本得到解答了,当你疑惑一些问题时,源码是最好的解释。 :-)

P.S. Python版本: 2.7.8 变量一般有三种风格:
引用式:变量是对象的名字,在运行时可以绑定到任意对象上,比如python。
值式:变量是存储位置的名字,在编译时绑定已经完成,运行时不可以改变,比如c。
混合式:某些类型是值式的,某些类型是引用式的,比如c#的struct和class。
c++比较特殊,基本上可以说是值式的,但是由于有别名存在,所以也有些引用式的特点。

引用式和值式的区别就是在赋值操作上,引用式的赋值是变量名的重新绑定,而值式的赋值是对象的拷贝。

他们两者是可以互相模拟的。引用式的想要有值式的赋值,只需要显式的拷贝或者copy-on-write就可以了。而值式的想要有引用式的赋值只需要使用指针就可以了。

你可能只是习惯了c/c++的值式的风格,还没适应引用式的风格。

看起来可能风格统一比较好。但是实际用起来我觉得c#的混合式是最好用的。 其实现在大部分的语言都是这样的:对象以引用的方式提供给编程者,对象赋值只是多个变量指向同一个对象。
大概只有C/C++的赋值是真的拷贝一份。
a = 258
在Python看来就是:
创建一个PyIntObject对象,值为258;a是一个指向PyObject的指针,将a指向此PyIntObject对象
之所以能这么干就和 @蓝色的答案解释的一样,所有的PyObject都有同样的头部。 在Python中有些对象是可以在原处进行改变的(即可变对象),这种对象包括了列表、字典、集合和一些自定义的对象。而对于整数和字符串等不可变对象是不会存在题主所说的问题。比如:
>>> a = 123
>>> b = a
>>> a = 321
>>> print a, b
321 123
问题的关键是,你写下y=x时,其实并没有新建一个y,而是一个类似c++中引用的机制,具体可以这样看:

>>> x = [1,2,3,4]
>>> y = x
>>> id(x)
43246536L
>>> id(y)
43246536L

所以x和y其实是一个东西。

如果要复制一个list,需要使用
>>> y = list(x)

或者

>>> y = x[:] 你加上“指针”一起理解。 你想深拷贝就用y=x[:]。

其实也没啥不好的,py的对象分为可变和不可变两种,只要理解了这一点一切都很清晰。 id()
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn