Python的基础--对象 转
对象(Objects)
是python中数据的抽象,python中所有的数据均可以用对象或者是对象之间的关系来表示。每个对象均有标识符(identity)、类型(type)、值(value)
。
- 标识符。对象一旦创建,那么它的标识符就不会改变,可以把标识符看作对象在内存中的地址。is 操作可以用来比较两个对象的标识符,函数id()用来返回对象标识符(python中返回对象在内存中的地址)。
- 类型。对象的类型也是不可变的,对象的类型决定了该对象支持的操作,另外也决定了该对象可能的值。type()函数返回一个对象的类型。
- 值。一些对象的值可以改变,我们叫它可变对象,字典和列表均属于可变对象;值不可改变的对象我们叫它不可变对象,数字、字符串、元组均属于不可变对象。
在python中,不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传地址。
可变对象与不可变对象
python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象指的是,对象的内容可变,而不可变对象是指对象的内容不可变。
不可变(immutable)对象:int、字符串(string)、float、数值型(number)、元组(tuple)。
可变(mutable)对象:字典型(dictionary)、列表型(list)。
一、不可变对象
由于Python中的变量存放的是对象引用,所以对于不可变对象而言,尽管对象本身不可变,但变量的对象引用是可变的。
i = 73
i += 2
(点小图查看大图)
从上面图示得知,对象73和对象75并没有变化,变化的只是创建了一个新的对象,改变了变量的对象的引用。看看下面的代码,更能体现这一点:
#因为258是int对象,是不可变对象的。所以下面3个id的值都是一样的,最后一句的结果也是为True
#有点奇怪的是为什么在IDLE,和在脚本执行的结果不太一样。所以下面的代码请在脚本中执行。 print(id(258))
a = 258
print(id(a))
b = 258
print(id(b))
print(a is b)
总结一下,不可变对象的优缺点。
优点是:这样可以减少重复的值对内存空间的占用。
缺点是:我要修改这个变量绑定的值,如果内存中没用存在该值的内存块,那么必须重新开辟一块内存,把新地址与变量名绑定。而不是修改变量原来指向的内存块的值,这回给执行效率带来一定的降低。
二、可变对象
其对象的内容是可以变化的。当对象的内容发生变化时,变量的对象引用是不会变化的。如下面的例子:
m=[5,9]
m+=[6]
(点小图查看大图)
函数参数
Python函数参数对于可变对象,函数内对参数的改变会影响到原始对象;对于不可变对象,函数内对参数的改变不会影响到原始参数。原因在于:
1、可变对象,参数改变的是可变对象,其内容可以被修改。
2、不可变对象,改变的是函数内变量的指向对象。
有关可变对象和不可变对象的介绍,简单的介绍到这里。
对象的回收机制
python不像C那样需要显式地回收对象占用的空间,python内核中有垃圾回收机制,当一个对象不可达时,就会交由垃圾回收机制处理。
一些对象引用了一些外部资源,例如打开的文件或者窗口。通常我们认为当这些对象被垃圾回收机制回收时,它占用的外部资源即被释放。但是,垃圾回收机制并不一定会回收这些对象,因此这些对象提供了显式的方法(通常是_close()_
)用来释放外部资源。程序中最好使用显式的方法来释放外部资源,一般可以使用 _try...finally_
方便地释放。
对象的类型
对象的类型几乎影响了该对象的所有功能,在某种程度上,对象的标识符也受其类型的影响。
>>> sum = 15
>>> sum_add = 12 + 3
>>> sum is sum_add
True
>>> sum = 15000000
>>> sum_add = 10000000 + 5000000
>>> sum is sum_add
False
>>> sum_add == sum
True
对于不可变对象(这里是int),当我们需要一个新的对象(sum_add = 12 + 3)时,python可能会返回已经存在的某个类型和值都一致的对象(sum)的引用。当然,这里只是可能会返回已经存在的对象,要看python的具体实现。同样是创建新的对象sum_add = 10000000 + 5000000,python并没有把值和类型都一样的sum返回给sum_add。
>>> value = []
>>> value_1 = []
>>> value is value_1
False
>>> value == value
True
>>> value = value_1 = []
>>> value is value_1
True
对于可变对象,当我们需要新的对象时,python一定会为我们新建一个。注意,这里value = value_1 = []
将会创建一个空的列表对象,然后同时返回给value和value_1。
扑朔迷离的不可变对象
首先看下面的代码:看我怎么改变不可变对象的值
>>> mutability = [1, 2, 3, 4]
>>> immutability = (0, mutability, 5)
>>> immutability
(0, [1, 2, 3, 4], 5)#查看可变对象与不可变对象的标识符(内存地址)
>>> id(mutability)
28356200
>>> id(immutability)
28048640#对可变对象与不可变对象都做一些改变
>>> mutability[2] = "see here!"
>>> immutability
(0, [1, 2, 'see here!', 4], 5)#查看改变后的可变对象与不可变对象的标识符(内存地址)
>>> id(mutability)
28356200
>>> id(immutability)
28048640
这里元组immutability中一个元素为可变对象列表mutability,当我们改变mutability的值时,号称不可变对象的元组的值似乎发生了变化。这又是为什么呢?
回答这个问题前,先总结下上面这段代码发生了什么:不可变对象A包含了一个对可变对象B的引用,可变对象B的值发生改变时,不可变对象A的值似乎会发生改变。
那么,为什么我们仍认为A是不可变对象呢?因为A仍然包含对象B,而B的标识符并没有发生变化,也就是说A的所有元素的标识符并没有发生变化。
看内存的布局是怎样的:
(点小图查看大图)
可以看出a是一个list列表类型的对象,它是一个可变对象,所以修改它的值不会创建新的对象。但是b是一个不可变对象,只要修改它的值,就会重新创建对象,注意,这里并没有修改它的值,因为它的所有元素的标识符并没有变化。
再看下面的例子:
>>> a = 2
>>> b = (1, a, 3)
>>> b
(1, 2, 3)
>>> id(a)
23112444
>>> id(b)
27983104>>> a += 10
>>> b
(1, 2, 3)
>>> id(b[1])
23112444
>>> id(b)
27983104>>> id(a)
23112324
在执行a+=10之前的内存布局为:
(点小图查看大图)
执行完a+=10的指令之后的内存布局为:
(点小图查看大图)
这里仅仅是原来的int(2)这个对象的引用数目减1.
在来一个狠的,在上面代码的基础上再来一个:
>>> b
(1, 2, 3)>>> b[1] = 13
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment>>> b[1]
2
通过元组类型的对象b对其中的一个int类型对象赋值,这样的话,因为int是不可变对象,所以会重新申请新的内存,那么同样会引起元组b中的xxx引用变量的改变,那么这样就真正的改变了元组b对象的某个元素的标识符。导致真正的改变了不可变元组对象b,这时就会报错。
修改上面的一些bug:
1. 首先id(a)函数是查看引用变量a所指向的对象的标识符,也就是内存地址。并不是引用变量a的内存地址。
2. 不管是元组还是列表,它们的元素存储的都是某个真实对象的引用,并不存储这个对象,因为python中一切皆对象。
先看一个内存结构,然后在看代码:
(点小图查看大图)
>>> a = (1,2,3)
>>> b = [1,2,3]
>>> id(a)
19840616
>>> id(b)
28577384
>>> id(a[0])
20032264
>>> id(b[0])
20032264
转载于:https://www.cnblogs.com/zengkefu/p/5506727.html
Python的基础--对象 转相关推荐
- python之⾯向对象基础
python之⾯向对象基础 ⼀. 理解⾯向对象 ⾯向对象是⼀种抽象化的编程思想,很多编程语⾔中都有的⼀种思想. 例如:洗⾐服 思考:⼏种途径可以完成洗⾐服? 答: ⼿洗 和 机洗. ⼿洗:找盆 - 放 ...
- 【Python基础入门系列】第10天:Python 类与对象
首先,我已经假定你是个萌新或已经看了无数遍的垃圾文章,然后依然搞不懂类和对象,但是呢起码知道有类和对象这么两个玩意儿,我觉得有必要找一篇生动形象的示例来讲解. 由于你可能没有编程经验, 所以无法从学过 ...
- Python 线程障碍对象 Barrier - Python零基础入门教程
目录 一.Python 线程障碍对象 Barrier 简介 二.Python 线程障碍对象 Barrier 原理 三.Python 线程障碍对象 Barrier 函数介绍 四.Python 线程障碍对 ...
- python 类和对象_Python零基础入门学习33:类与面向对象编程:类的继承
注:本文所有代码均经过Python 3.7实际运行检验,保证其严谨性. 本文字数约1300,阅读时间约为3分钟. Python面向对象编程 类的继承机制 如果一个类A继承自另一个类B,就把继承者类A称 ...
- Python零基础速成班-第9讲-Python面向对象编程(上),对象和类、初始化、继承、重写、多态、类方法、组合
Python零基础速成班-第9讲-Python面向对象编程(上),对象和类.初始化.继承.重写.多态.类方法.组合 学习目标 修饰器 面向对象编程:对象和类.初始化.继承.重写.多态.类方法.组合 课 ...
- 【Python零基础入门篇 · 7】:Python中的注释、字符串的常见操作、对象的布尔值
文章目录 Python中的注释 单行注释 多行注释 中文编码声明注释 字符串的常见操作(1) 编码解码的操作 增删改查以及分割 查找:find().index 统计:count() 替换:replac ...
- 【python语言基础】疑难点整理2
[python语言基础]疑难点整理1 第五章 在python语法中,循环体中的语句没有做限制,因此,可以是任何合法语句,当然也可以是循环语句.这样就形成了循环语句的嵌套. while循环语句和for循 ...
- Python培训基础教程都教哪些
根据相关数据统计,目前学习Python技术的同学大多数是零基础,都是从其他行业转型来学习的,那么Python培训基础教程都教哪些呢?好不好学呢?来看看下面的详细介绍. Python培训基础教程都教哪些 ...
- Python的基础,Python的101
近年 来,Python已经成为全世界最流行的编程语言之一.它是一种高级通用编程语言. 本文将重点介绍对所有初学者Python程序员都很重要的基本语法.数据类型.控制流等概念. 当然小编这里也准备一份适 ...
最新文章
- web3j官网的完整中文翻译(java开发区块链以太坊应用的开源类库)
- jvm垃圾回收机制和常见算法
- 使用Java创建内存泄漏
- 10个强大的Ajax jQuery文件上传程序
- linux下,MySQL默认的数据文档存储目录为/var/lib/mysql。
- SilverLight之我见
- MySQL update慢问题解决
- XCode 遇到的问题
- 结队编程之——阅读分析队友的代码(C++自动生成数学试卷)
- 企业集团合并财务报表
- 《穿越计算机的迷雾》读书笔记八
- 51单片机温控风扇仿真原理图 C语言程序,51单片机智能温控风扇程序
- python支持向量机 股票_测 python 利用SVM预测股票涨跌
- 手机内存卡RAW无法格式化的解决办法
- 西藏自治区林芝市谷歌高清卫星地图下载(百度网盘离线包下载)
- 微信中怎样查看微信热点?分享技巧!微信中如何查看微信热点?
- MacBook+eGPU编译安装pytorch、tensorflow(OSX10.13.3,python3.6,cuda9.1,cudnn7)(未完成)
- px、pt和em的区别
- 计算数据的经验分布函数与MATLAB作图
- 毕业了能考计算机二级考试,大学毕业一定要考计算机二级考试吗?
热门文章
- matlab 多 带阻,matlab程序之——滤波器(带通-带阻
- java stringbuffer长度限制_Java中的String、StringBuffer和StringBuilder
- Java文档阅读笔记-Guide to the Hibernate EntityManager
- echarts 地图 dispatchaction不好使_数据分析帝:广东省客户数量地图展示,如何通过python实现?...
- uibot css selector定位,UiBot如何使用CSS Selector
- pandas绘图_Pandas内置绘图方法(线型图、柱状图、密度图)
- 【线性代数本质】1:向量究竟是什么
- 栈溢出笔记1.2 覆盖EIP
- c++ winpcap开发(4)
- C++11 并发指南五(std::condition_variable 详解)