-day16--深浅拷贝&&nolocal关键字与总结

day16 阶段总结

课程目标:对第二模块 “函数和模块” 阶段的知识点进行总结和考试,让学员更好的掌握此模块的相关知识。

课程概要:

  • 知识补充
  • 阶段总结(思维导图)
  • 考试题

1.知识补充

1.1 nolocal关键字

在之前的课程中,我们学过global关键字。

name = 'root'


def outer():
    name = "海贼王"

    def inner():
        global name
        name = 123

    inner()
    print(name)


outer()
print(name)

其实,还有一个nolocal关键字,用的比较少,此处作为了解即可。

name = 'root'


def outer():
    name = "海贼王"

    def inner():
        nonlocal name # 让name指向上一级的内存地址
        name = 123

    inner()
    print(name)


outer()
print(name)
name = 'root'


def outer():
    name = 'geek'

    def func():
        name = "海贼王"

        def inner():
            nonlocal name
            name = 123

        inner()
        print(name)

    func()
    print(name)


outer()
print(name)

# 多个nonlocal一级一级往上找
name = 'root'


def outer():
    name = 'geek'

    def func():
        nonlocal name
        name = "海贼王"

        def inner():
            nonlocal name
            name = 123

        inner()
        print(name)

    func()
    print(name)


outer()
print(name)

1.2 yield from

在生成器部分我们了解了yield关键字,其在python3.3之后有引入了一个yield from。

# 遇到 yield from 可以进入到另外的生成器函数中执行,当执行外完毕后继续执行原来的生成器函数。
def foo():
    yield 2
    yield 2


def func():
    yield 1
    yield from foo()
    yield 1


for item in func():
    print(item)

# 输出
1
2
2
1

# 如果只有yield 没有from就只会得到一个生成器对象
def foo():
    yield 2
    yield 2


def func():
    yield 1
    yield  foo()
    yield 1


for item in func():
    print(item)
#输出
 1
<generator object foo at 0x0000017DC823BC10>
1

1.3 深浅拷贝

  • 浅拷贝

    • 不可变类型,不拷贝。

      # 深浅拷贝一般都是说的可变类型:`set` `list` `dict` (可变类型在进行深浅拷贝时无意义-内部都不会去拷贝,永远是同一块内存地址。)
      import copy
      
      v1 = "海贼王"
      print(id(v1)) # 2634991171792
      
      v2 = copy.copy(v1) # 浅拷贝
      print(id(v2)) # 2634991171792
      # 不可变类型,不会拷贝而是指向同一块内存地址
      

      按理说拷贝v1之后,v2的内存地址应该不同,但由于python内部优化机制,内存地址是相同的,因为对不可变类型而言,如果以后修改值,会重新创建一份数据,不会影响原数据,所以,不拷贝也无妨。

    • 可变类型浅拷贝:针对拷贝类型,只拷贝第一层。内部的不可变类型&可变类型都不会被拷贝

      # 可变类型,只拷贝第一层。
      import copy
      
      v1 = ["海贼王", "root", [44, 55]]
      print(id(v1))  # 140405837216896
      print(id(v1[2]))  # 140405837214592
      
      v2 = copy.copy(v1)
      print(id(v2))  # 140405837214784
      print(id(v2[2]))  # 140405837214592
      
      # 浅拷贝
      import copy
      
      v1 = ["海贼王", "root", [44, 55]]
      v2 = copy.copy(v1)
      
      print(id(v1))  # 2058892622848
      print(id(v2))  # 2058892981440
      
      # 可变类型之浅拷贝,列表会重新拷贝一份,注:拷贝的是列表,而不是列表中的数据
      print(id(v1[2]))  # 2058893546240
      print(id(v2[2]))  # 2058893546240
      
  • 深拷贝

    • 不可变类型,不拷贝

      import copy
      
      v1 = "海贼王"
      print(id(v1))  # 1888115587280
      
      v2 = copy.deepcopy(v1) # 深拷贝对不可变类型,不会拷贝而是指向同一块内存地址
      print(id(v2))  # 1888115587280
      

      特殊的元组:

      • 元组元素中无可变类型,不拷贝

        import copy
        
        v1 = ("海贼王", "root")
        print(id(v1))  # 1796403825792
        
        v2 = copy.deepcopy(v1)
        print(id(v2))  # 1796403825792
        
      • 深拷贝,对于可变类型,无论在那一层都会被拷贝,不可变类型永远不会被拷贝

        import copy
        
        v1 = ("海贼王", "root", [11, [44, 55]])
        v2 = copy.deepcopy(v1)
        
        print(id(v1))  # 2464296276096
        print(id(v2))  # 2464295962240
        
        # 列表指向了一个不可变类型,不会被拷贝,所有内存地址一样
        print(id(v1[0]))  # 2464296171728
        print(id(v2[0]))  # 2464296171728
        
        # 列表中的列表,可变类型,无论多少层都会被拷贝,所以内存地址不一样
        print(id(v1[2]))  # 2464296318400
        print(id(v2[2]))  # 2464296276864
        
      • 元素的元素中有可变类型,找到所有【可变类型】或【含有可变类型的元组】 均拷贝一份

        import copy
        
        v1 = ("海贼王", "root", [11, [44, 55], (11, 22), (11, [], 22), 33])
        v2 = copy.deepcopy(v1)
        
        print(id(v1))  # 1343966889792
        print(id(v2))  # 1343972069888
        
        print(id(v1[2]))  # 1343971486976
        print(id(v2[2]))  # 1343972070208
        
        print(id(v1[2][1]))  # 1343972071040
        print(id(v2[2][1]))  # 1343972070848
        
        print(id(v1[2][2]))  # 1343966874752
        print(id(v2[2][2]))  # 1343966874752
        
        print(id(v1[2][3]))  # 1343971463232
        print(id(v2[2][3]))  # 1343972069824
        
    • 可变类型,找到所有层级的 【可变类型】或【含有可变类型的元组】 均拷贝一份

      import copy
      
      v1 = ["海贼王", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]]
      v2 = copy.deepcopy(v1)
      
      print(id(v1))  # 1343966889792
      print(id(v2))  # 1343972069888
      
      print(id(v1[2]))  # 1343971486976
      print(id(v2[2]))  # 1343972070208
      
      print(id(v1[2][1]))  # 1343972071040
      print(id(v2[2][1]))  # 1343972070848
      
      print(id(v1[2][2]))  # 1343966874752
      print(id(v2[2][2]))  # 1343966874752
      
      print(id(v1[2][3]))  # 1343971463232
      print(id(v2[2][3]))  # 1343972069824
      
      import copy
      
      v1 = ["海贼王", "root", [44, 55]]
      v2 = copy.deepcopy(v1)
      
      print(id(v1))  # 2244897715712
      print(id(v2))  # 2244897674112
      
      
      print(id(v1[2]))  # 140563140392256
      print(id(v2[2]))  # 140563140535744
      

    总结:

    • 浅拷贝,针对可变类型只拷贝第一层,内部不可变类型&可变类型都不会被拷贝
    • 深拷贝,对于可变类型无论在那一层都会被拷贝,元组中如果有可变类型,也会被拷贝。而不可变类型永远不会被拷贝
    • 特殊的元组,浅拷贝,永远不会被拷贝;深拷贝,当元素的元素中都是不可变类型时,永远不会被拷贝,如果元素中有可变类型,元组在深拷贝时也会被拷贝。

2.阶段总结

思维导图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值