浅拷贝 VS 深拷贝

# In[]
# list 生成一个新的引用对象,只是用alst完成初始化
alst = [1,2,3,4,5]
blst=list(alst)
alst.append(6)
print(blst) # In[]
alst = [1,2,3,4,5]
blst=alst # 浅拷贝,两者同时变化
alst.append(6)
print(blst) # In[]
from copy import copy alst = [1,2,3,4,5]
blst=alst.copy() # 浅拷贝,两者同时变化
alst.append(6)
print(blst) # In[]
import copy
alst = [1,2,3,4,5]
blst=copy.deepcopy(alst) # 深拷贝,可以认为是用alst初始化一个新的对象
alst.append(6)
print(blst)

此处,对可变类型而言,深拷贝其实就是创建了一个新的引用对象,可以认为原来的只是用来做初始化用的。新旧有变化对彼此都没有影响了。浅拷贝可以认为就是起了个别名。

由于这层原因,当可变类型作为函数参数时,尤其要谨慎处理。首先考虑初始化,如果存在None,该怎么处理,其次如果你不想修改传入参数的值,那么要给类或者函数的属性创建一个副本或者说只是拿传入的参数作为初始化,务必保证,函数内部修改可变类型变量时,形参传入的变量不会受到影响。

'''
the default value of paramter is None
'''
import copy
# tag::BUS_CLASS[]
class Bus: def __init__(self, passengers=None):
if passengers is None:
self.passengers = []
else:
self.passengers = list(passengers) def pick(self, name):
self.passengers.append(name) def drop(self, name):
self.passengers.remove(name)
# end::BUS_CLASS[] bus1 = Bus(['a','b','c'])
bus2 = copy.copy(bus1)
bus1.pick('d')
bus1.drop('a')
print(bus2.passengers)
bus3= copy.deepcopy(bus1)
print(bus3.passengers)
bus1.pick('a')
bus1.drop('d')
print(bus3.passengers)
print(bus1.passengers)

  

此时如果对默认参数处理不好,会引起很诡异的事情。但是如果用list生成一个新的对象,就会避免这个问题。

'''
Mutable Types as Parameter Defaults:Bad Idea
''' # tag::HAUNTED_BUS_CLASS[]
class HauntedBus:
"""A bus model haunted by ghost passengers""" def __init__(self, passengers=[]): # <1>
# should be list function to initialization the attribute
self.passengers = passengers #list(passengers) # <2> def pick(self, name):
self.passengers.append(name) # <3> def drop(self, name):
self.passengers.remove(name)
# end::HAUNTED_BUS_CLASS[] bus1 = HauntedBus(['Alice', 'Bill'])
print(bus1.passengers)
bus1.pick('Charlie')
bus1.drop('Alice')
print(bus1.passengers) bus2 = HauntedBus()
bus2.pick('Carrie')
print('bus2.passengers:',bus2.passengers) bus3 = HauntedBus()
print('bus3.passengers:',bus3.passengers)
bus3.pick('Dave')
print('bus3.passengers:',bus3.passengers)
print(bus2.passengers is bus3.passengers)
print('bus1.passengers:',bus1.passengers)

  

还有,这个程序,把形参改变了,本来不该改变的。

'''
here the attribute passengers should be initialized using a list func. ''' # tag::TWILIGHT_BUS_CLASS[]
class TwilightBus:
"""A bus model that makes passengers vanish""" def __init__(self, passengers=None):
if passengers is None:
self.passengers = [] # <1>
else:
# this can change the passengers when you change self.passengers
self.passengers = passengers #<2> def pick(self, name):
self.passengers.append(name) def drop(self, name):
self.passengers.remove(name) # <3>
# end::TWILIGHT_BUS_CLASS[] basketball_team = ['Sue', 'Tina', 'Maya', 'Diana', 'Pat']
bus = TwilightBus(basketball_team)
bus.drop('Tina')
bus.drop('Pat')
print(basketball_team)

  

这几个程序大家都看到了,其实很关键的一个地方是list函数的使用。test =  list(alst)相当于将alst 进行深拷贝,改变alst时,test不会随之改变,改变test时,alst也不会有影响。也可以理解为将alst作为参数,对元素追个转换,生成一个新的list并返回给test。因此,两者之间不再有影响。

chap8-fluent python的更多相关文章

  1. 学习笔记之Fluent Python

    Fluent Python by Luciano Ramalho https://learning.oreilly.com/library/view/fluent-python/97814919462 ...

  2. 「Fluent Python」今年最佳技术书籍

    Fluent Python 读书手记 Python数据模型:特殊方法用来给整个语言模型特殊使用,一致性体现.如:__len__, __getitem__ AOP: zope.inteface 列表推导 ...

  3. Fluent Python: memoryview

    关于Python的memoryview内置类,搜索国内网站相关博客后发现对其解释都很简单, 我觉得学习一个新的知识点一般都要弄清楚两点: 1, 什么时候使用?(也就是能解决什么问题) 2,如何使用? ...

  4. Python深入学习之《Fluent Python》 Part 1

    Python深入学习之<Fluent Python> Part 1 从上个周末开始看这本<流畅的蟒蛇>,技术是慢慢积累的,Python也是慢慢才能写得优雅(pythonic)的 ...

  5. Fluent Python: Classmethod vs Staticmethod

    Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别: 给出的结论是一个非常有用(Classmethod), 一个不太有用(Static ...

  6. Fluent Python: @property

    Fluent Python 9.6节讲到hashable Class, 为了使Vector2d类可散列,有以下条件: (1)实现__hash__方法 (2)实现__eq__方法 (3)让Vector2 ...

  7. Fluent Python: Mutable Types as Parameter Defaults: Bad Idea

    在Fluent Python一书第八章有一个示例,未看书以先很难理解这个示例运行的结果,我们先看结果,然后再分析问题原因: 定义了如下Bus类: class Bus: def __init__(sel ...

  8. 《Fluent Python》---一个关于memoryview例子的理解过程

    近日,在阅读<Fluent Python>的第2.9.2节时,有一个关于内存视图的例子,当时看的一知半解,后来查了一些资料,现在总结一下,以备后续查询: 示例复述 添加了一些额外的代码,便 ...

  9. Fluent Python: Slice

    Pyhton中序列类型支持切片功能,比如list: >>> numbers = [1, 2, 3, 4, 5] >>> numbers[1:3] [2, 3] tu ...

  10. fluent Python

    1.1 Python风格的纸牌 Python collections模块中的内置模块:namedtuple https://www.liaoxuefeng.com/wiki/0013747381250 ...

随机推荐

  1. Java线程--Semaphore使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11872132.html Java线程--Semaphore使用 Semaphore是信号量, ...

  2. Java线程--ReentrantLock使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871593.html Java线程--ReentrantLock使用, 互斥锁: Reent ...

  3. Java线程--ThreadPoolExecutor使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871132.html Java线程--ThreadPoolExecutor使用 public ...

  4. 一张图让你看懂 iPhone 各种分辨率问题! #DF

    话不多说,直接看图! Source: paintcodeapp.com

  5. 已完成的python项目-环境离线部署

    python环境离线部署 当前生产环境中,有很多基于python开发的工具需要使用. 由于python工具往往涉及到很多依赖,在线状态下,可以通过pip requirements来管理安装. 但有时候 ...

  6. Scala中的流程控制

    一.分支控制if-else //Scala中if-else语句中,代码块内最后一句代码就是返回值 def main(args: Array[String]): Unit = { var age:Int ...

  7. HTML笔记整理--下节

    欢迎来到HTML基础笔记下节部分! 内联样式 当特殊的样式需要应用到个别元素时,就可以使用内联样式. 使用内联样式的方法是在相关的标签中使用样式属性.样式属性可以包含任何 CSS 属性.以下实例显示出 ...

  8. Java不支持协程?那是你不知道Quasar!

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 在编程语言的这个圈子里,各种语言之间的对比似乎就一直就没有停过,像什么古早时期的"PHP是世界上最好的语言"就不提了,最近我 ...

  9. 深入理解Java类加载机制,再也不用死记硬背了

    谈谈"会"的三个层次 在<说透分布式事务>中,我举例里说明了会与会的差别.对一门语言的学习,这里谈谈我理解的"会"的三个层次: 第一层:了解这门语言 ...

  10. 16进制转字符串得到flag

    工业协议分析2 666c61677b37466f4d3253746b6865507a7d