python中对象相等判断(is、==与

发布时间:2019-09-21 10:51:46编辑:auto阅读(1672)

    之前转载过一篇有关java的equals与==差别的文章(详见http://blog.csdn.net/xiaohukun/article/details/78439580
    最近学习python的时候又看到了这个运算符,于是便了解了一下python中对象比较相关的知识,特此分享。(根据python版本不同可能会有些许不同)

    一、对象的要素

    python中对象包含三个基本要素,分别是:

    • id(身份标识) 可以理解为c里面的指针或内存位置
    • type(数据类型)
    • value(值)

    例1

    >>>a1=1
    >>>a2=1
    >>>print(id(a1))
    140611277590096
    
    >>>print(id(a2))
    140611277590096
    
    >>>a1=[1,2]
    >>>a2=[1,2]
    >>>print(id(a1))
    4477835456
    
    >>>print(id(a2))
    4477833512
    
    >>> class test:
    ...     def __init__(self,s):
    ...             self.s=s
    ...
    >>> t1=test("hello")
    >>> t2=test("helo")
    >>> print(id(t1))
    4511016936
    >>> print(id(t2))
    4511017008

    可以看出,number和string在赋值时,对于同一值不重新分配内存,所以同一个值id相同。
    而其他数据类型(包括自定义类)在每次赋值时都会为每一个对象开辟一个新内存予以存储,所以id不同。

    二、==与is的使用

    例2

    >>>a1=1
    >>>a2=1
    >>>print(a1==a1)
    True
    
    >>>a1=[1,2]
    >>>a2=[1,2]
    >>>print(a1==a2)
    True
    
    >>>print(a1 is a2)
    a2
    
    t1=test("hello")
    t2-=test("hello")
    print(t1==t2)
    False
    
    print(t1 is t2)
    

    ==用于判断数值是否相等,因此对于六大基本数据类型而言,相同的值即可判定相等。而对于其他类的实例化对象而言,存储和比较的可以认为是内存地址或者id,因此此时即使拥有相同属性也会因为id不同而被判定为不相等。
    is,这是用于直接比较二者的地址是否相同

    也就是是说java中的equals与==,类似于python中的==与is

    三、__dict__的使用

    我们知道java中可以通过重写类equals的方法实现类对象的属性相等判断,可是python中并没有这样的函数,除了自定义equals函数有没有其他方便的实现方式呢?

    利用python中的属性dict可以实现
    例3

    class test:
        clsvar=1
        def __init__(self,invar):
            self.invar=invar
    print(test.__dict__)
    输出:{'clsvar': 1, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x100aecf50>}
    
    t1=test(1)
    t2=test(1)
    print(t1.__dict__)
    输出:{'invar': 1}
    
    print(t1==t2)
    输出:False
    
    print(t1.__dict__==t2.__dict__)
    输出:True

    其中clsvar称之为类变量,invar称之为实例变量
    python中__dict__ 是一个字典,键是属性名,值为属性值。
    Python的实例有自己的dict,它对应的类也有自己的dict (但是有些特殊的对象是没有dict属性的,这里不做讨论)

    当打印类的dict属性时,列出了类所包含的属性,包括一些类内置属性和类变量clsvar以及构造方法init

    而实例变量则包含在实例对象t1的dict属性中,利用这一点可以很容易实现比较t1和t2的实例变量是否相同。

    既然谈到了 __dict__,那就稍微介绍一下它的规则:

    一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。
    例4

    #实例先检查对象自身
    t1.clsvar=10
    print(test.clsvar)
    输出:1
    
    print(t1.clsvar)
    输出:10
    
    #没类对象先检查类自身
    test.clsvar=20
    print(test.clsvar)
    输出:20
    
    print(t1.clsvar)
    输出:10
    
    print(t2.clsvar)
    输出:
    
    #给类和实例中未定义的变量赋值
    test.m=5
    t1.x=5
    print(test.m)
    print(t1.x)
    输出:55
    
    t3=test(1)
    print(t3.m)
    输出:5
    
    print(t3.x)
    报错:AttributeError: test instance has no attribute 'x'

    最后附上一个将字典转换成对象的小技巧,如果我们有一个字典如下:

    dict={"a":1,
         "b":2,
         "c":3}

    现在想将其转换为一个对象,通常会这样写:

    class test:
        def __init__(self,dict):
            self.a=dict['a']
            self.b=dict['b']
            self.c=dict['c']

    但是在了解了dict属性之后可以这样写:

    class test:
        def __init__(self,dict):
            self.__dict__.update(dict)

    update可以将实例对象的变量换为dict所含的变量与值,这里是全部替换,即使原来定义了一个实例变量x,update之后该变量也将不存在

关键字