Skip to content

Latest commit

 

History

History
79 lines (60 loc) · 3.67 KB

ReferenceAndObject.md

File metadata and controls

79 lines (60 loc) · 3.67 KB

对象和引用

对象:

内存中存放的一块逻辑的整体数据对象具有唯一的标识符,对象包括属性(Properties)和方法(Methods),属性就是需要记忆的信息,方法就是对象能够提供的服务。在面向对象面向对象(object-oriented)编程中,对象(Object)是某一个类(Class)的实例(Instance)。在 Python shell 中输入 dir(2) 可以知道,在 Python 中 2 并不是简单的一个整数,而且包含了很多内置的方法。

引用:

引用像指针一样指向一块内存空间,跟 C 语言中的指针相似。

举例:

整数对象

简单的赋值语句 a = 10000, a 指向了 10000 所在的那块内存。a 引用的对象就是存放 10000 的内存地址。
is 判断两个变量是否引用同一个对象,id() 取得对象的内存地址

a = 10000 
b = 10000 
print a is b

输出是 False, 可以知道 a,b 是两个不同的对象,每次创建都会申请新的内存

a = 1
b = 1
print a is b

输出是 True,a,b又是相同的对象了。这是因为在 Python 启动的时候,常用的整数[-5, 256]就建立好,不销毁的对象,也就是 a,b 都引用相同的一块内存(存放1的内存),每次创建这个范围内的整数对象不会申请新的内存。这是个设计上的均衡,用一些内存的浪费,来提高大部分程序的运行速度

容器对象

Python 中容器(可以包含其他对象的对象)中存放的对象实际上都是引用

In [17]: a = [[]] * 5
In [18]: a
Out[18]: [[], [], [], [], []]
In [19]: a[1].append(0)
In [20]: a
Out[20]: [[0], [0], [0], [0], [0]]
In [21]: a[0] is a[1]
Out[21]: True

a 列表有五个相同的元素,这五个元素都是对同一个空列表的引用(21行),所以改变其中任何一个元素(不改变对象引用的情况下),所有的五个元素都会同时进行改变

list 是可变对象,在 list 扩容的时候有几种方法

In [6]: a = [1]
In [7]: id(a)
Out[7]: 28048488
In [8]: a = a + [2]
In [9]: a
Out[9]: [1, 2]
In [10]: id(a)
Out[10]: 28047696

可以看出使用 + 修改列表,创建了新的列表(对象),a 已经不是原先那个对象,不存放在原先那个内存地址了,进行了大量的内存复制

In [21]: a = [1]
In [22]: id(a)
Out[22]: 20913832
In [23]: a += [2]
In [24]: id(a)
Out[24]: 20913832

使用 += 修改列表,并没有创建新的列表(对象),还存放在原先那个地址。(extend 与 += 几乎相同,只是 extend 多了调用函数的时间)。

In [29]: a = [1]
In [30]: id(a)
Out[30]: 28048704
In [31]: a.append(2)
In [32]: id(a)
Out[32]: 28048704

使用 append 修改列表,也没有创建新的列表,也是存放在原先那个地址。append 会进行提前的内存申请,扩容时会更快。但是 append 只能进行单个元素的扩容,内存消耗较大。

所以列表扩容的时候尽量使用 extend 或者 append(当然 list 如果进行频繁大量空间的扩容,肯定会造成效率问题)。

string 和 tuple 都是不可变对象,所以在进行改变的时候肯定都会创建新的对象。(根据这个原理,可以思考下为什么 string 进行合并的时候为什么建议用 join)

函数对象

在 Python 中函数也是对象,所以我们可以像整数赋值一样,将函数赋值给一个变量,将函数作为参数传递给另一个函数,我觉得这也是为什么Python中存在 decorator 的一个原因

参考:

http://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)

Python群 22507237 的 @冒泡 大神