• Python Revisited (变量)


    @

    首先,需要指出的是,Python的变量采用的是对象绑定的方式,在程序运行过程中,要时刻注意,对象的变化和共享。

    =

    第一种情况 = 右边是值 这种情况并不会产生歧义

    a = 1
    a = '1'
    a = [1]
    a = {1:'1'}
    

    第二种情况 = 右边是对象引用(变量——个人的说法)

    b = 1
    a = b
    

    当变量(b)为固定类型——float, int, str, frozenset, tuple等等都是没关系的。
    当变量为可变的数据类型——dict, list, set, 就存在风险。

    b = [1, 2, 3]
    a = b
    a[0] = 4
    a, b # ([4, 2, 3], [4, 2, 3])
    

    浅拷贝

    b = a[ : ] #a 为列表 这种情况是浅拷贝 比=略强

    a = [1, ['2', 5], 3]
    b = a[:]
    a[0] = 2
    b[1][0] = 'two'
    a, b #([2, ['two', 5], 3], [1, ['two', 5], 3])
    

    以下复制的方式都是浅拷贝:
    .copy()
    dict()
    list()
    set()
    a[:]

    深拷贝`

    a = [1, ['2', 5], 3]
    b = copy.deepcopy(a)
    a[0] = 2
    b[1][0] = 'two'
    a, b #([2, ['2', 5], 3], [1, ['two', 5], 3])
    

    函数的默认参数为可变类型时 危险

    def append_if_even(x, lst=[]):  #从对象绑定的角度考虑,合情合理
        if x % 2 == 0:
            lst.append(x)
        print(lst)
    
    append_if_even(2) #[2]
    append_if_even(2) #[2, 2] 
    append_if_even(2) #[2, 2, 2]
    append_if_even(2) #[2, 2, 2, 2]
    
    

    全局变量与临时变量

    函数里面创建的变量属于临时变量,在这上面摔的跤太多了。

    global

    def remain():
        global REMAIN
        REMAIN = 3
    def sum_and_add(a, b):
        remain() #得执行一次
        return a + b + REMAIN
    sum_and_add(1, 2) # 6
    
    
    

    在函数里面进行复制

    就像在上面讲的,=只是赋值,在函数里面玩这种很容易就凉凉。

    def test(a):
    	b = a # a 属于 list  如果你不希望改变a的值可以采用 b= a[:] 如果是多重的可以考虑深拷贝
    	b.append(1)
    a = [1]
    test(a)
    a #[1, 1]
    
    

    再看一个例子

    def main():
        a = [1]
        print(id(a))
        ccc(a)
        print(id(a))
        print(a)
    def ccc(a):
        a= sorted(a)  #这一步令a指向了新的内存地址,所以下面对a操作都不会影响最初的a
        print(id(a))
        a.append(1)
        print(id(a))
        ccd(a)
    def ccd(a):
        a.append(1)
        print(id(a))
    main()    
    """
    2431712245320
    2431712245512
    2431712245512
    2431712245512
    2431712245320
    [1]
    """
    
    def main():
        a = [1]
        print(id(a))
        ccc(a)
        print(id(a))
        print(a)
    def ccc(a):
        a.sort()  #并没有改变a的指向,不过需要注意的是 [].sort() is None
        print(id(a))
        a.append(1)
        print(id(a))
        ccd(a)
    def ccd(a):
        a.append(1)
        print(id(a))
    main()    
    """
    2431712245384
    2431712245384
    2431712245384
    2431712245384
    2431712245384
    [1, 1, 1]
    """
    

    numpy里的bug?

    ndarray里面用id蛮奇怪的,list是都不一样的,同学说可能是沿袭了C。

    A = np.array([[1, 2], [3, 4]])
    print(id(A))
    for i in range(2):
        for j in range(2):
            print(id(A[i, j])) 	
    
    
    #2392090756480
    #2392073432760
    #2392073432760
    #2392073432760
    #2392073432760
    
    

    下面这个例子,符合我们的预期

    A = np.arange(4).reshape(2, 2)
    a = A[0,...]
    print(id(a[0]), id(A[0, 0]), id(A[1, 1]))
    a[0] = 999
    print(id(a[0]), id(a[1]), id(A[0, 0]), id(A[1, 1]))
    a, A
    
    #2392073432160 2392073432160 2392073432160
    #2392073432160 2392073432160 2392073432160 2392073432160
    #[121]:
    #(array([999,   1]), array([[999,   1],
    #        [  2,   3]]))
    

    下面的例子就不是了,为什么不改呢?

    A = np.arange(4).reshape(2, 2)
    a = A[np.array([[True, False], [False, True]])]
    #a = A[[0, 1], [0, 1] 同样不行
    print(id(a[0]), id(A[0, 0]), id(A[1, 1]))
    a[0] = 999
    print(id(a[0]), id(a[1]), id(A[0, 0]), id(A[1, 1]))
    a, A
    
    #2392073432064 2392073432064 2392073432064
    #2392073432064 2392073432064 2392073432064 2392073432064
    #(array([999,   3]), array([[0, 1],
    #        [2, 3]]))
    

    待续

  • 相关阅读:
    OBS推流工具
    Spring学习笔记(二)
    设计模式
    力扣刷题 二分法 leetcode 刷题 27,26,283,844,977
    论文笔记 Processing Private Queries over Untrusted Data Cloud through Privacy Homomorphism 通过隐私同态处理不可信数据云上的私有查询
    今日链表操作leetcode 24 交换链表中的相邻两个结点
    leetcode刷题 leetcode22中等题 有效括号生成
    npm镜像 yarn镜像 homebrew镜像 各种镜像
    mac m1 pro 搭建php环境
    华为弹性ecs(centOS7)环境构建笔记
  • 原文地址:https://www.cnblogs.com/MTandHJ/p/10528182.html
Copyright © 2020-2023  润新知