python 中的可变对象与不可变对象
近日辞职待工,没有实际的项目与大家分享。暂写写在实际运用python中遇到的关于可变对象和不可变对象的坑。
首先我们需要明确一个概念,在python中一且皆对象。我们一般定义一个变量a=0,其实质a是一个类型变量,python 会把a封装为一个pyObject。我后面会用type方法来说明这个问题。
说在前面,在python 中变量名是一个类似标签的东西。它之前是什么类型与它之后是什么类型完全没有关系。我们可以把它理解为一个贴纸,可以随意从区块A撕下来贴到区块B上。正因为有这个特点,我们在使用python 对变量赋值时就无需担心变量类型问题。当然,为了规范和后面代码维护方便,此种做法需要节制,不然会让自己都搞不清最终需要的对象到底个什么类型,不方便调程序。
不可变对象
不可变对象一般包括int, float, bool, str, tuple. 不可变对象在函数调用过程中不会被更改,除非重新赋值。
这个例子中,a的类型为 int 说明它是一个类实例对象,根据python官方文档https://docs.python.org/3/library/functions.html#int,显示 class int ,进一步证实我们开篇提到的问题。 我们看到将变量a传入函数addTwoNum 中,将a+b的值赋给a并返回。从结果上看a的值并没有发生改变。我们在来看看各个变量的id。
这里我们看到,a 和 c 的id 不一样,说明它们是两个独立的存储区域。我们在看另一种写法。
这里我们看到,a 的id发生了变化,而且巧合的是现在的a 的id和 c 一样。说明此时a 的指向已经发生了改变。通过这个例子我们可以下这么个结论:不可变对象的存储区域相互独立。每次产生以个新的不可变对象则重新开辟一块区域。
可变对象
可变对象主要包括:list, dict, set。可变对象在参数传递过程会被改变。下面给出一个简单的例子:
我们看到,函数的返回类型什么也没有,但是li 列表的值确实发生了变化,我们还观察到一个很有意思的事,li 中元素的id 值都顺延了,不知道是不是由于li 中值时连续的整数的原因。为了证明li 的首部没有变,及li 本身指向的区块没有变,我们加入打印li 的id 的语句
从图上可以发现,li 的id 确实没有改变。从而可以说明li 没有变,但其值发生了变化。
运用
在知道了不可变对象和可变对象的特性后 ,我们可以根据它们各自的特点避免一些坑,特别是可变对象。在申明函数时,若函数参数存在可变变量,如果不需要每次都产生新的存储空间,我们可以不用另加判断,其中特别需要注意的函数中的局部变量一定不能与全局变量重名。如果需要每次都产生新的存储空间,那么最好是在函数内部声明一个变量,然后最后返回。例如,第一种情况,不需要每次都产生新的存储空间。
每执行一次函数,li 就增加两个元素。这种特性,用在递归中有很好的效果。给出一个括号匹配的算法,其中就运用到了可变变量这个能不断修改元素、添加元素的特性。
def generateParenthesis(N):
ans = []
def backtrack(S = '', left = 0, right = 0):
if len(S) == 2 * N:
ans.append(S)
return
if left < N:
backtrack(S+'(', left+1, right)
if right < left:
backtrack(S+')', left, right+1) backtrack()
return ans
第二种情况,每次都需要开辟新的存储空间:
虽然不可变变量与可变变量是一个简单的问题,我们也不能小看它呀,有时往往就是这种细小的错误让人抓狂。简单的一篇博文,有不足之处请及时指出,共同进步。
python 中的可变对象与不可变对象的更多相关文章
- python中如何统计一个类的实例化对象
类中的静态变量 需要通过类名.静态变量名 来修改 :通过对象不能修改 python中如何统计一个类的实例化对象?? class Person: #静态变量count,用于记录类被实例化的次数 coun ...
- python中的函数的参数和可变参数
最近在搞python的过程中需要用到给函数传可变参数..所以去网上找前人的帖子学习了一下 为了尊重原作者,这里附上链接:http://www.cnblogs.com/tqsummer/archive/ ...
- python中表示False的一些内置对象
By default, an object is considered true unless its class defines either a __bool__() method that re ...
- 《python解释器源码剖析》第6章--python中的dict对象
6.0 序 元素和元素之间可能存在着某种关系,比如学生姓名和成绩.我希望能够通过学生的姓名找到这个学生的成绩,那么只需要将两者关联起来即可.字典正是这么做的,字典中的每个元素就是一个key:value ...
- Python探索记(16)——Python的可变类型与不可变类型
# @Time : 2017/7/8 17:49 # @Author : 原创作者:谷哥的小弟 # @Site : 博客地址:http://blog.csdn.net/lfdfhl # @DESC : ...
- 【Python核心编程笔记】一、Python中一切皆对象
Python中一切皆对象 本章节首先对比静态语言以及动态语言,然后介绍 python 中最底层也是面向对象最重要的几个概念-object.type和class之间的关系,以此来引出在python如何做 ...
- 【转】Python中自定义可迭代对象
python 中内置的可迭代的对象有 list.tuple.set.dict 等,那么我们自己怎么定义一个可迭代的对象呢?先来段代码吧 import re import reprlib RE_WORD ...
- Python中的几种数据类型
大体上把Python中的数据类型分为如下几类: Number(数字) 包括int,long,float,complex String(字符串) 例如:hello,"hello" ...
- 简单探讨python中的语句和语法
python程序结构 python"一切皆对象",这是接触python听到最多的总结了.在python中最基层的单位应该就是对象了,对象需要靠表达式建立处理,而表达式往往存在于语句 ...
- Python中的传参是传值还是传址?
传值:在C++中,传值就是把一个参数的值给这个函数,其中的更改不会影响原来的值. 传址:即传引用,直接把这个参数的内存地址传递进去,直接去这个内存地址上进行修改. 但是这些在Python中都没有,Py ...
随机推荐
- python - class类 (七) 三大特性 - 封装 结尾
封装: # 封装 #第一层,类就是麻袋,本身就是一种封装 #第二层,类中定义私有的,至在类的内部使用,外部无法访问 #第三层,封装在于明确区分内外,使得类实现者可以修改封装内的东西二不影响外部调用者 ...
- ROS Kinetic Install on Debian 9
Not Succesed! 1. 配置源$ sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release - ...
- Linux: 介绍make menuconfig中的每个选项含义【转】
转自:http://blog.csdn.net/gaoyuanlinkconcept/article/details/8810468 介绍make menuconfig中的每个选项含义 Linux 2 ...
- sqlserver中将查询结果拼接成字符串
#for xml path(param)--将查询结果以xml格式输出 select id,name from table1 for xml path --id和name为table1的真实字段 - ...
- 内核中 subsys_initcall 以及初始化标号
今天在看内核中无线的实现时,发现一个调用 subsys_initcall(cfg80211_init);搜索一些资料: subsys_initcall 的定义在 include/linux/init. ...
- CSS伪元素before、after妙用
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 【linux】tcpdump抓包
tcpdump -i eth0 host 192.168.11.22 -w ./target.cap 上面指令,抓取eth0中与192.168.11.22相关的流量,保存到target.cap中
- 使用mybatis-spring-boot-starter如何打印sql语句
只需要将接口文件的日志设置为debug即可. 例如你的mapper接口所在的文件夹是 com.demo.mapper 那么在application.properties配置文件中添加 logging. ...
- poj2155二维树状数组区间更新
垃圾poj又交不上题了,也不知道自己写的对不对 /* 给定一个矩阵,初始化为0:两种操作 第一种把一块子矩阵里的值翻转:0->1,1->0 第二种询问某个单元的值 直接累计单元格被覆盖的次 ...
- python 全栈开发,Day51(常用内置对象,函数,伪数组 arguments,关于DOM的事件操作,DOM介绍)
昨日内容回顾 1.三种引入方式 1.行内js <div onclick = 'add(3,4)'></div> //声明一个函数 function add(a,b){ } 2. ...