补充(不太常用): nolocal关键字、 yield from、深浅拷贝

一、nolocal关键字

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

name = 'root'


def outer():
    name = "张三"

    def inner():
        global name   # 修改全局变量name为123
        name = 123

    inner()
    print(name)


outer()
print(name)  # 指向全局变量,但是全局变量已经被修改,所以此处name=123

其实,还有一个nolocal关键字,用的比较少,此处作为了解即可。主要是修改上级作用域的变量。

name = 'root'


def outer():
    name = "张三"

    def inner():
        nonlocal name   # 此处修改name 指向的是上一级作用域的name,即name = "张三"
        name = 123

    inner()
    print(name)   # 此处name为123


outer()
print(name)  # 此处仍然指向全局,name为root
name = 'root'


def outer():
    name = 'zhangsan'

    def func():
        name = "张三"       # 被下方的nonlocal修改name为123

        def inner():
            nonlocal name    # 修改上一级变量name为123
            name = 123

        inner()
        print(name)   # 123

    func()
    print(name)   # zhangsan


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


def outer():
    name = '李四'    # 被nonlocal ,name为张三,又被nonlocal 为123

    def func():
        nonlocal name     # 被nonlocal ,name为123
        name = "张三"  

        def inner():
            nonlocal name
            name = 123

        inner()
        print(name)    # 123

    func()
    print(name)  # 123


outer()
print(name)  # root

二、 yield from

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

def foo():
    yield 2
    yield 2
    yield 2


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


for item in func():
    print(item)

三、深浅拷贝(面试出现概率高)

- 深浅拷贝一般都是说的可变类型:setlistdict(不可变类型在进行深浅拷贝时无意义-内部都不会去拷贝,永远是同一块内存地址)

import copy

v1 = "张三"
v2 = copy.copy(v1)
print(id(v1))  # 140663937558640
print(id(v2))  # 140663937558640


- 浅拷贝,只拷贝第一层的可变类型。
- 深拷贝,拷贝所有层的可变类型 + 元素中如果有可变类型,也会被拷贝。


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

import copy

v1 = ["张三", "root", [44, 55]]
v2 = copy.copy(v1)

print(id(v1))  # 140370940277440
print(id(v2))  # 140370940279744   v1与v2内存地址不同,此处拷贝的列表本身,而不是列表里边的数据,列表本身存储地址不同,被成功拷贝

print(id(v1[2]))  # 140364497610864
print(id(v2[2]))  # 140364497610864   但是v1的第2个元素和v2的第2个元素位置相同,可变类型没有被拷贝


# 深拷贝,对于可变类型无论在那一层都会被拷贝,不可变类型永远不会被拷贝。

import copy

v1 = ["张三", "root", [44, 55]]
v2 = copy.deepcopy(v1)

print(id(v1))  # 140541799775168
print(id(v2))  # 140541799773120   最外层成功拷贝

print(id(v1[0]))  # 140687559878768   但是内部的不可变类型,内层地址一样,没有被拷贝
print(id(v2[0]))  # 140687559878768
  
print(id(v1[2]))  # 140526364734720   可变类型被拷贝
print(id(v2[2]))  # 140526364882368


# 特殊的:元组,不可变类型如果遇到
#    - 浅拷贝,永远不会拷贝。
#    - 深拷贝,当元素的元素中都是不可变类型时,永远不会拷贝;如果元素中有可变类型,也会被拷贝

import copy

v1 = (11, 22, [11, 22], 33)
v2 = copy.deepcopy(v1)
print(id(v1))    # 2774135044032   
print(id(v2))    # 2774135044112

1.浅拷贝

【1】不可变类型,不拷贝
import copy

v1 = "张三"
print(id(v1)) # 140652260947312

v2 = copy.copy(v1) 
print(id(v2)) # 140652260947312

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

【2】可变类型,只拷贝第一层。
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

2. 深拷贝

【1】不可变类型,不拷贝
import copy

v1 = "张三"
print(id(v1))  # 140188538697072

v2 = copy.deepcopy(v1)
print(id(v2))  # 140188538697072
【2】特殊的元组:
- 元组元素中无可变类型,不拷贝
import copy

v1 = ("张三", "root")
print(id(v1))  # 140243298961984

v2 = copy.deepcopy(v1)
print(id(v2))  # 140243298961984
- 元素元素中有可变类型,找到所有【可变类型】或【含有可变类型的元组】 均拷贝一份
import copy

v1 = ("张三", "root", [11, [44, 55], (11, 22), (11, [], 22), 33])
v2 = copy.deepcopy(v1)

print(id(v1))  # 140391475456384
print(id(v2))  # 140391475456640

print(id(v1[2]))  # 140352552779008
print(id(v2[2]))  # 140352552920448

print(id(v1[2][1]))  # 140642999940480
print(id(v2[2][1]))  # 140643000088832

print(id(v1[2][2]))  # 140467039914560
print(id(v2[2][2]))  # 140467039914560

print(id(v1[2][3]))  # 140675479841152
【3】可变类型,找到所有层级的 【可变类型】或【含有可变类型的元组】 均拷贝一份
import copy

v1 = ["张三", "root", [11, [44, 55], (11, 22), (11, [], 22), 33]]
v2 = copy.deepcopy(v1)

print(id(v1))  # 140391475456384
print(id(v2))  # 140391475456640

print(id(v1[2]))  # 140352552779008
print(id(v2[2]))  # 140352552920448

print(id(v1[2][1]))  # 140642999940480
print(id(v2[2][1]))  # 140643000088832

print(id(v1[2][2]))  # 140467039914560
print(id(v2[2][2]))  # 140467039914560

print(id(v1[2][3]))  # 140675479841152
print(id(v2[2][3]))  # 140675480454784
import copy

v1 = ["张三", "root", [44, 55]]
v2 = copy.deepcopy(v1)

print(id(v1))  # 140405837216896
print(id(v2))  # 140405837214784


print(id(v1[2]))  # 140563140392256
print(id(v2[2]))  # 140563140535744
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值