• 对象引用、可变性和垃圾回收


    1.python中变量是什么?

    在数学概念中,变量表示没有固定值且可以改变的数值。
    在计算机系统中,变量表示一段或者多段用来存储数据的内存。
    变量名都是指代的一个指针。

    在GO语言里面,变量总是有固定的类型,变量类型决定了数据在内存中的长度存储格式。

    在python中,变量进行初始化的时候可以不指定类型,那它是如何存储的?
    你可以将变量看成标签,比如
    a = 1
    现在将a这个便签绑定在1这个int类型的对象上面。
    a = “kebi”
    现在又将a重新绑定在”kebi“这个str类型的对象上面。
    这种操作只能在动态类型的语言中才能完成。因为指代的不是同一种类型的对象。

    在静态类型的语言中,编译之后的机器码不会有变量,直接使用内存地址来访问目标对象。
    要阐述python中的变量,还是要从面向对象的角度来理解。

    2.is和==的区别

    is:比较双方是否是一个对象,其实时对象操作
    ==:比较两个对象的值是否相等,内部使用__eq__进行判断

    在使用等号进行赋值操作的时候会创建一个新的对象

    a = [1,2,3]
    b = [1,2,3]
    print(id(a),id(b))  #1553861243912 1553861191560
    print(a is b)  #False  并不是同一个对象
    print(a == b)  #True   但是值是相等的

      如果是对象重新赋值,那么就是同一个值

    c = a
    print(id(a),id(c))  #2320288838728 2320288838728
    print(c is a)  #True
    print(c == a)  #True

    但是,例如总是有的
    在python中使用小整数、短字符串进行赋值时,为了节约内存空间,指向同一个内存地址。

    e = 1
    f = 1
    print(id(e),id(f)) #1426481376 1426481376
    k,j = ("abc","abc")
    print(id(k),id(j))  #2347188715000 2347188715000

    3.del语句和垃圾回收机制

    python中垃圾回收的算法时采用引用计数。比如:
    a = 1
    b = a
    现在计数2
    del a #将a变量删掉,并将计数器减1.
    当你将变量的计数器删为0的时候,python解释器会将这个对象删除。

    当我们在做垃圾回收操作的时候,我们可以重写__del__语句,这样在调用del操作的时候就能实现自己的逻辑。

    4.一个经典的参数错误

    def add(a,b):
        a += b #a.extend(b)
        return a
    
    
    a = 1
    b = 2
    print(add(a,b))  #3
    print(a)  #1
    print(b)  #2
    
    c = [1,2]
    d = [3,4]
    print(add(c,d))  #[1, 2, 3, 4]
    print(c)  #[1, 2, 3, 4]
    print(d)  #[3, 4]
    
    e = (1,2)
    f = (3,4)
    print(add(e,f))  #(1, 2, 3, 4)
    print(e)  #(1, 2)
    print(f) #(3, 4)

    这里你肯定要问,都是使用add操作,为啥在使用list的时候,会改变另一个对象的值。
    下面的实例也会更能说明问题:

    class Company:
        def __init__(self,staffs=[]):
            self.staffs = staffs
    
        def add(self, staffs_name):
            self.staffs.append(staffs_name)
    
    com1 = Company(['ke','mao'])
    
    com2 = Company()
    com2.add('niao')
    print(com1.staffs)  #['ke', 'mao']
    print(com2.staffs)  #['niao']
    
    com3 = Company()
    com3.add('ming')
    print(com1.staffs)  #['ke', 'mao']
    print(com2.staffs)  #['niao', 'ming']
    print(com3.staffs)  #['niao', 'ming']

    这里改变com3.staffs去意外的改变了com2.staffs,但是com1.staffs为啥又没有改变了?
    原因是
    com2 = Company()
    com3 = Company()
    都是用是默认的staffs=[]这个空list,所以com2.staffs和com3.staffs引用的是同一个对象,
    同时这个对象还是可变的,com2和com3中,这两个对象的add方法操控的是同一个对象,所以才会出现上述问题。
    但是为啥com1不受影响了?['ke','mao']和[]不是同一个对象。
    所以在以list等可变类型作为为参数的时候,我们必须清楚它可能被其它对象修改。

  • 相关阅读:
    3. 算法分析
    4. union-find算法
    1.基础编程模型和数据抽象
    2. 背包,队列和栈
    .NET Core 单元测试
    ASP.NET Core Web API
    ASP.NET Core MVC 之区域(Area)
    ASP.NET Core MVC 之依赖注入 Controller
    ASP.NET Core MVC 之依赖注入 View
    微服务架构学习与思考(04):微服务技术体系
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/11288361.html
Copyright © 2020-2023  润新知