文档章节

Python的mutable值碎碎念

守恒的猫
 守恒的猫
发布于 2017/04/10 10:16
字数 658
阅读 6
收藏 0

如下案例:

>>> def test(a, b=[]):
...     b.append(a)
...     return b

>>> test(1)
[1]
>>> test(2)
[1, 2]
>>> test(3)
[1, 2, 3]

 

是由于对于python的可变类型list,set,dict等,它的关键字变量默认值是在函数定义的时候存在func_defaults里的,又因为可变类型是传引用,因此每一次调用都是变化的。

 

[另一方面,在嵌套函数中,python2的内层函数无法获取外层函数不可变变量,但可以访问可变变量,因此通常这样写

def test():

    a = [1]

    def t():

        print a[0]

    t()

把变量放在一个mutable里]X

这里有一个严重失误,像这样的闭包,python内存函数是可以访问外层的变量的,但对immutable变量不允许修改,外面有个a=1,里面可以print a,可以a=2,但不允许a += 2,之前的“无法获取”是错误的,谨记!!!

——————————————————————————————————————————————

说到mutable,一个值得探讨的问题就是copy和deepcopy。通常来说一个浅拷贝只拷贝可变参数的引用,当原数据发生修改时拷贝数据也会修改,考虑如下case:

>>> a = [1,2,[12]]
>>> b = a
>>> a = [2,3,[23]]
>>> a
[2, 3, [23]]
>>> b
[1, 2, [12]]

嘿?说好的同时修改呢?

实际上是因为a进行了一个赋值操作而非对象内的数据修改,因此指向了另外一片内存。浅拷贝的case如下:

>>> a = [1,2,[12]]
>>> b = a
>>> a[1] = 3
>>> a[2].append(3)
>>> b
[1, 3, [12, 3]]
>>>

对于序列来说,会发生浅拷贝的情况有切片,工厂函数list()和copy模块等。

深拷贝顾名思义是整个复制重开内存,这里不再赘述,不过有一点,python对于不可变变量,深拷也是直接拷引用的,反正不可变,节省空间~case如下:

>>> c = 1
>>> d = deepcopy(c)
>>> id(c),id(d)
(140569092332408, 140569092332408)

要特别注意元组类型,考虑如下case:

>>> a = (1,2)
>>> b = deepcopy(a)
>>> id(a),id(b)
(4482226008, 4482226008)
>>> a = (1,[12])
>>> b = deepcopy(a)
>>> id(a),id(b),id(a[0]),id(b[0]),id(a[1]),id(b[1])
(4482223208, 4482225792, 140569092332408, 140569092332408, 4482452008, 4482450280)

 

当元组数据均为immutable时,深拷是拷引用

当数据中有mutable时,深拷回开辟新内存,其中,immutable的变量指向同一处,mutable的指向不同处

另外,当元组中有可变数据进行浅拷时,可变数据修改也会同时发生。

————————————————————————————————————————————

immutable数据是可以自定义的,只要重写继承的object的__setattr__和__delattr__

 

  1. class Immutable(object):  
  2.     def __setattr__(self, *args):  
  3.         raise TypeError("can't modify the value of immutable instance")  
  4.   
  5.     __delattr__ = __setattr__  
  6.   
  7.     def __init__(self, value):  
  8.          super(Immutable, self).__setattr__("value", value)  

© 著作权归作者所有

共有 人打赏支持
守恒的猫
粉丝 4
博文 40
码字总数 21817
作品 0
房山
私信 提问
Python3开发随记(2)实例

<碎碎念> 今天在公司终于把jQuery搜索插件的功能写完了,已经能实现同步GET提交查询参数并正确显示视图,重构了三遍自己才觉得代码凑合能看,和高手还是有距离的,继续努力吧。 晚上继续看P...

hosealee
2016/04/13
98
0
Waston+Python,6行代码实现音频转文字,轻松做字幕~

几行代码,抱上IBM爸爸大腿,实现音频快速转文字~用到了IBM Waston的Speech to text(目前还是个demo) 碎碎念的废话~ 前几天工作中遇到需要把音频转为文字稿的任务,顺便学了个新词语:扒词...

莉莉安的向日葵
2018/04/27
0
0
Python3开发随记(3)数据类型

<碎碎念> 上一个话题暂时不写了,直接写代码不好,还是先从基础开始吧 </碎碎念> Python3开发随记(3)数据类型 从这篇开始还是先看基础吧,直接看代码不好,另外我是一边看书一边写笔记的,...

hosealee
2016/04/17
72
0
理解 Python object 的 mutable 和 immutable

在 Python 的世界里,一切皆对象,每个对象各包含一个 idendity、type 和 value。 identity: 可理解为 object 的内存地址空间,其值可由 id() 函数获取,一旦 object 被创建,其 identity 将...

koala bear
2013/08/14
0
0
你们知道开源中国最讽刺的一件事情是什么吗?

开源资讯除了偶尔发点小编的碎碎念和公告之外,只要是正式的文章,100%是转载,但是却在每篇文章的结尾自欺欺人的加上这么一段话: 本站文章除注明转载外,均为本站原创或编译。欢迎任何形式...

小宏的爹
2017/05/31
409
2

没有更多内容

加载失败,请刷新页面

加载更多

面向对象接口多态

第3天 面向对象 今日内容介绍  接口  多态  笔记本案例 今日学习目标  写出定义接口的格式  写出实现接口的格式  说出接口中成员的特点  接口和抽象类的区别  能够说出使用多...

stars永恒
2分钟前
0
0
摄像头基础介绍

一、摄像头结构和工作原理. 拍摄景物通过镜头,将生成的光学图像投射到传感器上,然后光学图像被转换成电信号,电信号再经过模数转换变为数字信号,数字信号经过DSP加工处理,再被送到电脑中...

天王盖地虎626
3分钟前
0
0
浅谈一致性Hash原理及应用

在讲一致性Hash之前我们先来讨论一个问题。 问题:现在有亿级用户,每日产生千万级订单,如何将订单进行分片分表? 小A:我们可以按照手机号的尾数进行分片,同一个尾数的手机号写入同一片/...

Java干货分享
25分钟前
1
0
React SSR样式及SEO的实践

前一篇主要记录了一下SSR配置以及结合Redux的使用。这里简单说一下React SSR中样式处理和更优雅的SEO SSR样式 在React客户端渲染,添加样式很容易。写一个css样式文件,在对应组件中引用。标...

前端小攻略
32分钟前
5
0
华为手机太猛!余承东吹的牛今天都实现了

华为是世界上少有的在2B和2C领域同时取得成功公司。如今,华为消费者业务的营收,已经在华为总营收中占据“半壁江山”。 12月27日,华为董事长郭平在新年致辞中披露,预计2018年华为预计实现...

linux-tao
42分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部