• Python进阶:对象复制与比较,分深浅,见真假


    "==" 与 is

      python 为 10 开辟内存空间, a与b同时指向这块内存,即a与b的值相等,a与b的id也相等.因此 a==b 与 a is b 都返回True:

    a = 10
    b = 10
    print(a == b)
    #True
    print(id(a))
    #140726165951808
    print(id(b))    
    #140726165951808
    print(a is b)
    #True
      在[-5,256]范围内的整数会有上面代码的性能优化,而不在这范围内的数字就会重新开辟内存空间。
      【实验证明,下面代码只在终端中执行Python命令行时才有效,而在执行脚本时整型的数据都会分配同一个空间】
    a = 257
    b = 257
    print(a == b)
    #True
    print(id(a))
    #139636876096528
    print(id(b))
    #139636905893680
    print(a is b)
    #False
      元组虽是不可变类型,但如果嵌套了可变类型(list),那么元组就变成是可变的了
    t1 = (1, 2, [3, 4])
    t2 = (1, 2, [3, 4])
    print(t1 == t2)
    #True
    
    t1[-1].append(5)
    print(t1 == t2)
    #False

    浅拷贝(shallow copy) 与 深拷贝(deep copy)

      浅拷贝

      使用数据类型本身的构造器,是浅拷贝

    l1 = [1, 2, 3]
    l2 = list(l1)
    #l2
    #[1, 2, 3]
    
    print(l1 == l2)
    #True
    print(l1 is l2)
    #False
    
    s1 = set([1, 2, 3])
    s2 = set(s1)
    #s2
    #{1, 2, 3}
    
    print(s1 == s2)
    #True
    print(s1 is s2)
    #False

      切片也是浅拷贝

    l1 = [1, 2, 3]
    l2 = l1[:]
    
    print(l1 == l2)
    #True
    print(l1 is l2)
    #False

      copy.copy()浅拷贝

    import copy
    l1 = [1, 2, 3]
    l2 = copy.copy(l1)
    print(l1 is l2)
    #False

      对于元组,这些操作都是返回指向同一元组(1,2,3)的引用

    import copy
    t1 = (1, 2, 3)
    #t2 = tuple(t1)
    #t2 = t1[:]
    #t2 = copy.copy(t1)
    t2 = copy.deepcopy(t1) #如果元组中不只是原子类型,比如有list,dict就可以用deepcopy
    
    print(t1 == t2)
    #True
    
    print(t1 is t2)
    #True

      以下代码 l2 = list(l1)表示 l2 指向 l1浅拷贝生成的新对象, 而对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址)

    l1 = [[1, 2], (30, 40)]
    l2 = list(l1)

      由于l1与l2是两个指向不同的对象,所以 l1指向的列表增加元素不会改变 l2指向的列表

    l1.append(100) 
    print(l1)
    #[[1, 2, 3], (30, 40), 100]
    print(l2)
    #[[1, 2, 3], (30, 40)]

      由于浅拷贝对象中的元素是引用原始元素的内存地址,因此对于可变类型(list)增加了3,l2与l1中list的是同一个引用,因此也是[1,2,3]

    l1[0].append(3)
    print(l1)
    #[[1, 2, 3], (30, 40), 100]
    print(l2)
    #[[1, 2, 3], (30, 40)]

      由于 tuple是不可变类型,因此修改后l1指向重新分配的一个新元组的引用。

    l1[1] += (50, 60)
    print(l1)
    #[[1, 2, 3], (30, 40, 50, 60), 100]
    print(l2)
    #[[1, 2, 3], (30, 40)]

      深拷贝

      拷贝出来的新对象完全独立于原对象,修改操作与原对象互不影响

    import copy
    x = [1]
    x.append(x)
    print(x)
    # [1, [...]]
    
    y = copy.deepcopy(x)
    print(y)
    # [1, [...]]
    print(x is y) #False
    print(x == y) #RecursionError: maximum recursion depth exceeded in comparison 递归错误

    参考

      https://www.cnblogs.com/wilber2013/p/4645353.html

      极客时间《Python 核心技术与实战》专栏

      

  • 相关阅读:
    python-初始网络编程
    mysql 之优化
    python 操作Mysql
    白话SCRUM之一:SCRUM 的三个角色
    白话SCRUM 之三:sprint backlog
    Scrum 之 product Backlog
    9.为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗?
    8.如何自己设计一个类似 Dubbo 的 RPC 框架?
    7.分布式服务接口请求的顺序性如何保证?
    6.分布式服务接口的幂等性如何设计(比如不能重复扣款)?
  • 原文地址:https://www.cnblogs.com/xiaoguanqiu/p/11018550.html
Copyright © 2020-2023  润新知