MST

星途 面试题库

面试题:Python变量相等性检查与对象生命周期

假设有两个列表list1 = [1, 2, 3]和list2 = [1, 2, 3],使用'=='和'is'检查它们的相等性,会得到不同结果。请从Python对象的创建、内存分配和垃圾回收机制角度,解释为什么会这样。如果要确保两个复杂自定义对象在值相等时,'is'也返回True,应该怎么做?
10.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
  1. '=='和'is'的区别及原因
    • '=='运算符
      • '=='比较的是两个对象的值(content)。在Python中,当我们创建list1 = [1, 2, 3]list2 = [1, 2, 3]时,两个列表虽然是不同的对象,但它们的值相同。所以list1 == list2会返回True。这是因为列表对象重写了__eq__方法,用于比较列表中的元素是否相同。
    • 'is'运算符
      • 'is'比较的是两个对象的身份(identity),也就是它们在内存中的地址。当创建list1 = [1, 2, 3]时,Python会在内存中为这个列表对象分配一块内存空间。当创建list2 = [1, 2, 3]时,又会分配另一块不同的内存空间,尽管它们的值相同。所以list1 is list2会返回False。这是因为在Python中,即使两个对象的值相同,也会为它们分配不同的内存地址(除了一些小整数和字符串的优化情况)。
      • 内存分配和垃圾回收机制角度
        • 内存分配时,对于每个新创建的列表对象,Python的内存管理系统会在堆内存中为其分配一块空间来存储列表的数据和相关元数据(如长度等)。当没有任何引用指向这些列表对象时(例如重新赋值list1 = Nonelist2也没有其他引用),垃圾回收机制会检测到这些对象无法访问,并回收它们所占用的内存空间。
  2. 确保复杂自定义对象在值相等时,'is'也返回True的方法
    • 使用单例模式。在Python中,可以通过以下方式实现单例模式:
      • 使用模块级别的变量
        class MyComplexObject:
            def __init__(self):
                pass
        my_obj = MyComplexObject()
        def get_my_obj():
            return my_obj
        
        在这个例子中,模块加载时会创建一个MyComplexObject的实例my_obj,通过get_my_obj函数获取的对象始终是同一个,这样使用is比较通过get_my_obj获取的对象时会返回True
      • 使用__new__方法
        class SingletonComplexObject:
            _instance = None
            def __new__(cls):
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
                return cls._instance
        obj1 = SingletonComplexObject()
        obj2 = SingletonComplexObject()
        print(obj1 is obj2) # 会返回True
        
        在上述代码中,__new__方法确保了无论创建多少次SingletonComplexObject的实例,始终返回同一个实例对象,从而保证了is比较返回True