python 有关引用的一些问题
python 有关引用的一些问题
print id.__doc__
id(object) -> integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
python中的引用对象特点:
- python不允许程序员选择采用传值还是传引用。
- Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过“传引用”来传递对象。
- 如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值'来传递对象。
- 当人们复制列表或字典时,就复制了对象列表的引用,如果改变引用的值,则修改了原始的参数。
- 为了简化内存管理,Python通过引用计数机制实现自动垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象。
参考
以下是一些例子:
In [19]:
# variable 动态创建一个新的变量,但是,list,tuple,dictionary 却不会创建新的实例
a= 1
b = a
print id(a)
print id(b)
b = 3
print "change b to 3 "
print "a: %s, b: %s" %(a ,b)
print "a id is : %s; b id is : %s" %(id(a),id(b))
out:
42295960
42295960
change b to 3
a: 1, b: 3
a id is : 42295960; b id is : 42295912
In [25]:
# list
a= [1,2,3]
b = a # 引用
print id(a)
print id(b)
b[2] = 6
print "change b to 3 "
print "a: %s, b: %s" %(a ,b)
print "a id is : %s; b id is : %s" %(id(a),id(b))
out:
66189960
66189960
change b to 3
a: [1, 2, 6], b: [1, 2, 6]
a id is : 66189960; b id is : 66189960
In [38]:
# list
a= [1,2,3]
b = a[:] # 值拷贝, 创建了新的对象实例
print id(a)
print id(b)
b[2] = 6
print "change b to 3 "
print "a: %s, b: %s" %(a ,b)
print "a id is : %s; b id is : %s" %(id(a),id(b))
out:
65422344
65421832
change b to 3
a: [1, 2, 3], b: [1, 2, 6]
a id is : 65422344; b id is : 65421832
In [32]:
# dictionary
a= {'ta':11,'tb':22,'tc':33}
b = a # 引用,改变的是原实例的值
print id(a)
print id(b)
b['tb'] = 6
print "change b to 3 "
print "a: %s,\n b: %s" %(a ,b)
print "a id is : %s;\n b id is : %s" %(id(a),id(b))
out:
66214904
66214904
change b to 3
a: {'tb': 6, 'tc': 33, 'ta': 11},
b: {'tb': 6, 'tc': 33, 'ta': 11}
a id is : 66214904;
b id is : 66214904
In [36]:
# tuple 元组用"()"标识。内部元素用逗号隔开。但是元组不能二次赋值,相当于只读列表。
a= (1,2,3)
b = a
print id(a)
print id(b)
# b[0] = 6
print "change b to 3 "
print "a: %s,\n b: %s" %(a ,b)
print "a id is : %s;\n b id is : %s" %(id(a),id(b))
out:
66132296
66132296
change b to 3
a: (1, 2, 3),
b: (1, 2, 3)
a id is : 66132296;
b id is : 66132296
In [9]:此案例的问题来自博文 ,经改进。如下
def add_list(p):
pt = p +[5,6] # 1
p = p + [5,6] # 2 1 和2 是等价的,没有将值返回, ‘=’左边的变量,都是函数内部生成的局部临时对象,并没有返回,故不会修改传入参数的值。
# 此处和静态语言的理解方式是一样的。
p1 = [1,2,3]
add_list(p1) #1 和2 是等价的,没有改变返回值
print p1
def add_list2(p):
p += [5,6]
p2 = [1,2,3]
add_list2(p2)
print p2
out:
[1, 2, 3]
[1, 2, 3, 5, 6]
此处‘=’号左边的p 应该是一个函数新建的一个局部的、临时的对象实例,等号的右边的p是才是函数传进来的,由于临时的“P”并没有返回,故肯定不会改变传入list的值。此处和静态语言应该是一致的。 所以,它并没有修改原来的p引用。
In [6]:
help('+=')
An augmented assignment expression like "x += 1" can be rewritten as
"x = x + 1" to achieve a similar, but not exactly equal effect. In the
augmented version, "x" is only evaluated once. Also, when possible,
the actual operation is performed *in-place*, meaning that rather than
creating a new object and assigning that to the target, the old object
is modified instead.
In [11]:
# 字典引用
a = []
b = {'num':0, 'sqrt':0}
resurse = [1,2,3]
for i in resurse:
b['num'] = i
b['sqrt'] = i * i
a.append(b)
print "a: ",a
d=[]
for i in resurse:
b['num'] = i
b['sqrt'] = i * i
d1 = b.copy()
d.append(d1)
print "d: ",d
c=[]
for i in resurse:
c.append({"num":i, "sqrt":i*i})
print "c: ",c
out:
a: [{'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}]
d: [{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9}]
c: [{'num': 1, 'sqrt': 1}, {'num': 2, 'sqrt': 4}, {'num': 3, 'sqrt': 9}]
b['num'] = i 和 b['sqrt'] = i * i 中的 b['num'] 和 b['sqrt'] 是已经压入list a 中元素的一个引用,故它可以在不断地改变list 内部变量的值。
单步调试可以看到,
a中值的变化情况:*以执行完语句a.append(b)为节点 *
[{'num': 1, 'sqrt': 1}]
--> [{'num': 2, 'sqrt': 4},{'num': 2, 'sqrt': 4}]
--> [{'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}, {'num': 3, 'sqrt': 9}]
在append(b)到list a之前获得b的值拷贝,将值append 到list a 也可以达到目标。如示例d所示。
当然,示例C是更加简洁的一个版本,这里应该还有迭代器的知识点,暂时还没折腾内部,待到下次和生成器一起分析。
python 有关引用的一些问题的更多相关文章
- python的引用计数分析(二)
python所有对象引用计数被减少1的情况: 一.对象的别名被赋予新的对象; a = 23345455 # 增加了一个引用 b = a # 增加了一个引用 print(sys.getrefcount( ...
- python按引用赋值和深、浅拷贝
按引用赋值而不是拷贝副本 在python中,无论是直接的变量赋值,还是参数传递,都是按照引用进行赋值的. 在计算机语言中,有两种赋值方式:按引用赋值.按值赋值.其中按引用赋值也常称为按指针传值(当然, ...
- 关于python如何引用excel文件
关于python如何引用excel文件 import pandas as pd #引用pandas库,as:将pandas简写为pd Nowcoder = pd.read_excel("1. ...
- python模块引用问题(比较杂乱,懒得整理)
1 在stackoverflows摘抄 If the import module in the same dir, use e.g: from . import core If the import ...
- 【Python】引用计数
一.概述 要保持追踪内存中的对象,Python使用了引用计数这一简单的技术. 二.引用计数的增减 2.1 增加引用计数 当对象被创建并(将其引用)赋值给变量时,该对象的引用计数被设置为1. 对象的引用 ...
- python模块引用梳理
文件组织结构: t ├── __init__.py ├── main.py ├── t1 │ ├── A.py │ └── __init__.py └── t2 ├── B.py └── __ ...
- python 传值引用和传参引用
调用同事的函数,传入goods_list,获取商品信息,然后将商品信息与goods_list的信息进行匹配,合并. 但是同事返回数据的同时改变了我传入的参数,goods_list.相当于传参引用,也就 ...
- 安装redis,以及python如何引用redis
下载 cd /usr/local/src/ wget http://download.redis.io/releases/redis-2.8.17.tar.gz 解压 tar -zxvf redis- ...
- 关于virtualenv python环境引用 pycharm相关配置的使用讨论
今天总算决定来搞一波以前从来没有弄清楚的环境问题,也觉得是时候弄明白了. 这里先说关于python的环境引用,再谈到virtualenv最后再谈论我使用的pycharm5.0关于是用python环境的 ...
随机推荐
- LeetCode 525. Contiguous Array
525. Contiguous Array Add to List Description Submission Solutions Total Accepted: 2476 Total Submis ...
- leetcode 427. Construct Quad Tree
We want to use quad trees to store an N x N boolean grid. Each cell in the grid can only be true or ...
- Spring实例化bean的几种方式
一,通过constructor实例化bean Spring可以实例化各种类型的类,不要求必须是JavaBean类型的类.在XML中配置类如下: <bean id="exampleBea ...
- About libcurl and cURL in PHP
今天在学习php时遇到要调用curl 库函数对特定url字符串进行访问操作,需要自己写一个方法进行调用,之前在linux系统中也有用到cURL 命令行工具执行对相关资源的获取,在wiki上找到了如下的 ...
- python marshal 对象序列化和反序列化
有时候,要把内存中的一个对象持久化保存到磁盘上,或者序列化成二进制流通过网络发送到远程主机上.Python中有很多模块提供了序列化与反序列化的功能,如:marshal, pickle, cPickle ...
- SpringMVC札集(04)——SpringMVC传递参数
自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View系列教程03–onL ...
- JMter参数化
参数化是干嘛的呢,咱们在调用接口的时候,有入参,那参数里面的值如果经常变化的话,就得每次去改了,很麻烦,这时候咱们就把需要经常变的值,改成可以变化的或者是咱们提前设置好的一些值,这样的话,调用的时候就 ...
- [Python] dict字典的浅复制与深复制
Python中针对dict字典有两种复制: (1)浅复制:利用 copy() 或者 dict() :复制后对原dict的内部子对象(方括号[]内元素)进行操作时,由浅复制得到的dict会受该操作影响 ...
- SQL查询执行步骤
1.总结 执行顺序 3.select ...聚合函数 from 表名 1.where ... 2.group by ... 4.having ... 5.order by ... 6.limit .. ...
- json中的dumps和loads
常用有2个方法,也是最基本的使用方法: 1.dumps:把字典转成json字符串 进行post的请求的时候就要用json.dumps来进行装换,利用get方法就可以不用了. 2.loads:把json ...