前面一篇文章介绍了一些Python对象的基本概念,这篇接着来看看Python对象相关的一些内容。

Python对象的比较

Python对象有三个要素:身份,类型和值,所以我们就分别从这三个角度出发看看对象之间的比较。

对象身份比较

对象身份的比较,其实就是比较对象的内存地址,即内建函数id()的结果比较。可以用来判断不同的变量是否指向了同一个地址。

直接看例子:

通过例子的输出可以得到,f1和f2指向了不同的对象(地址);但是,i1和i2却指向了相同的对象(地址)。

之所以产生这种差异,是因为Python对整数对象和字符串对象会进行缓存,所以没有产生新的对象,而是指向了缓存的对象。不同版本的Python处理缓存是不一样的,所以同样的例子可能产生不同的结果。

对于对象身份比较,还可以使用Python中的"is"关键字:

obj1 is obj2
# 等价
id(obj1) == id(obj2) obj1 is not obj2
# 等价
id(obj1) != id(obj2)

对象类型比较

通过type()内建函数,可以得到一个对象的类型,然后就可以进行类型比较了。

看一段代码:

例子中使用了三种方式进行对象类型的比较:

  • 直接将type(obj)与类型进行比较
  • 将type(obj)的身份跟类型的身份进行比较
  • 通过内建的isinstance()函数,判断一个对象是不是有特定类型实例化得到的
    • 其第一个参数为对象,第二个为类型名或类型名的一个列表
    • 其返回值为布尔型

简单看看前两种方式的区别,第一种方式是直接将两个类型对象的值进行比较;而第二种方式比较的是两个类型对象的身份,这种方式的原理是,如果两个类型对象的身份不同,那么两个类型对象的值肯定不同。

对象值比较

对于Python对象,可以直接使用比较操作符(>,<,==等)进行对象值的比较。关于Python的内建对象,有一套比较规则,比如两个list对象的比较就是按照list比较规则进行的。

这里我们就主要看看自定义类型的对象之间的比较。

自定义类型的对象值比较

在Python中,所有的类型都有一套用于比较的"魔术方法" ,对于自定义的类型,我们就可以通过实现这些方法来定义自定义类型的对象的比较行为:

  • __cmp__(self, other) : __cmp__ is the most basic of the comparison magic methods. __cmp__ should return a negative integer if self < other, zero if self == other, and positive if self > other.
  • __eq__(self, other) Defines behavior for the equality operator, ==.
  • __ne__(self, other) Defines behavior for the inequality operator, !=.
  • __lt__(self, other) Defines behavior for the less-than operator, <.
  • __gt__(self, other) Defines behavior for the greater-than operator, >.
  • __le__(self, other) Defines behavior for the less-than-or-equal-to operator, <=.
  • __ge__(self, other) Defines behavior for the greater-than-or-equal-to operator, >=.

看一个例子,我们定义了一个"语句"类型,并实现了一些比较方法,这样对于改类型的对象,我们就可以直接通过比较操作符进行对象值比较了。

有一点需要注意的是,关于自定义类型的对象,如果没有实现比较操作符对应的"魔术方法",那么将默认使用对象身份(id())进行比较。

"is"和"=="的差别

这里需要注意一下"is"和"=="之间的差别:

  • "is"用来比较对象的身份是否相等,也就是说,比较对象的内存地址是否相同(变量是否指向同一个对象)
  • "=="用来比较对象的内容(值)是否相等

看下面的代码:

对于变量c和d,由于数值超过了Python对整型数的缓存范围,所有d就会是Python生成的一个新的对象。因此,c和d的值是相同的,但是身份却是不同的。

可变对象和不可变对象

在Python中,一切都是对象,Python中不存在所谓的传值,一切传递的都是对象的引用(也可以认为是传址)。

上一篇文章中了解到,根据Python对象的类型,可以将Python对象分为:Type Object(类型对象)和Non-type Object(非类型对象)。

同样,根据对象的可变性,也可以将Python对象分为两类:可变(mutable)对象和不可变(immutable)对象。

  • 不可变(immutable)对象:对象的内容不可变,当尝试改变对象内容的时候,会创建一个新的对象;也就是说对象的身份(id())会发生变化
    • 例如:number、string,tuple
  • 可变(mutable)对象:对象的内容可变,当改变对象内容的时候,对象的身份(id())不会变化
    • 例如:list、dict、set

看一段简单的代码:

tuple是"可变的"

虽然元组对象本身是不可变的,但这并不意味着元组包含的可变对象也不可变。

看下面的例子:

现在我们根据下图分析这段代码,tpl这个元组的第四个元素比较特殊,是一个list;所以,在tpl中第四个元素存放的是这个list的地址(身份id(),引用)。

元组的不可变性就决定了tpl第四个元素对应的内容,即list的地址不能改变了,但是,这个地址37865712指向的内容是可以被改变的。

总结

本篇介绍了Python对象的比较,包括对象的身份,类型以及值的比较。对于自定义类型的对象,如果需要进行比较操作,可以通过自定义比较操作相关的"魔术方法"。

另外,文中简单介绍了Python对象的可变性,对比了可变(mutable)对象和不可变(immutable)对象之间的不同。

Python对象(下)的更多相关文章

  1. python 对象

    python 对象 在python中,对象就是为C中的结构体在堆上申请的一块内存,一般来说,对象是不能被静态初始化的,并且不能再栈空间上生存.本文主要对Python的基本数据类型做简单的介绍. PyO ...

  2. Python对象(译)

    这是一篇我翻译的文章,确实觉得原文写的非常好,简洁清晰 原文链接:http://effbot.org/zone/python-objects.htm ------------------------- ...

  3. Python对象体系揭秘

    Guido用C语言创造了Python,在Python的世界中一切皆为对象. 一.C视角中的Python对象 让我们一起追溯到源头,Python由C语言实现,且向外提供了C的API http://doc ...

  4. python学习笔记:python对象

    一.python对象 python使用对象模型来存储数据,构造任何类型的值都是一个对象.所有的python对象都拥有三个特性:身份.类型和值. 身份:每个对象都有一个唯一的身份标识自己,对象的身份可以 ...

  5. Python的下划线_

    1.单下划线(_) 通常情况下,单下划线(_)会在以下3种场景中使用: 1.1 在解释器中: 在这种情况下,"_"代表交互式解释器会话中上一条执行的语句的结果.这种用法首先被标准C ...

  6. 判断python对象是否可调用的三种方式及其区别

    查找资料,基本上判断python对象是否为可调用的函数,有三种方法 使用内置的callable函数 callable(func) 用于检查对象是否可调用,返回True也可能调用失败,但是返回False ...

  7. 【Python】 python对象的文件化 pickle

    pickle 之前隐隐约约在哪里看到过pickle这个模块但一直没怎么用过.然后让我下定决心学习一下这个模块的原因竟然是[妹抖龙女(男)主在工作中用到了pickle哈哈哈].嗯嗯,不扯皮了.pickl ...

  8. python环境下实现OrangePi Zero寄存器访问及GPIO控制

    最近入手OrangePi Zero一块,程序上需要使用板子上自带的LED灯,在网上一查,不得不说OPi的支持跟树莓派无法相比.自己摸索了一下,实现简单的GPIO控制方法,作者的Zero安装的是Armb ...

  9. python(七) Python中单下划线和双下划线

    Python中单下划线和双下划线: 一.分类 (1).以单下划线开头,表示这是一个保护成员,只有类对象和子类对象自己能访问到这些变量. 以单下划线开头的变量和函数被默认是内部函数,使用from mod ...

随机推荐

  1. PCL常见错误集锦

    来自微信公众号的分享 我刚刚开始接触PCL,懂的东西也很少,所以总是出现各种各样的问题,每次遇见问题的时候要查找各种各样的资料,很费时间.所以,今天我把我遇见的常见问题分享给大家,讲解的步骤尽量详细, ...

  2. 三篇文章了解 TiDB 技术内幕——说计算

    在这我们将关系模型简单理解为 Table 和 SQL 语句,那么问题变为如何在 KV 结构上保存 Table 以及如何在 KV 结构上运行 SQL 语句. 假设我们有这样一个表的定义: CREATE ...

  3. R语言-Paste函数

    该函数和excel中的&一样,可以将不同类型的数据放在一起. paste(....,sep="",collapse=NULL) ...表示要加在一起的数据类型,e.g ​p ...

  4. Qt实现探测当前有没有网络连接(Wi-Fi)——QNetworkConfigurationManager.isOnline()

    1.只需要探测当前有没有连上Wi-Fi(不用获取网络状态),可以调用<QNetworkConfigurationManager>类. QNetworkConfigurationManage ...

  5. 关于Mac上的开发工具

    如果是JavaScript语言的话用  Intellij IDEA 如果是C/C++语言的话用  XCode

  6. Oracle system表空间满的暂定解决方法

    Oracle system表空间满的暂定解决方法 数据库用的是Oracle Express 10.2版本的.利用Oracle Text做全文检索应用,创建用户yxl时没有初始化默认表空间,在系统开发过 ...

  7. Python中的高级turtle(海龟)作图(续)

    四.填色 color 函数有三个参数.第一个参数指定有多少红色,第二个指定有多少绿色,第三个指定有多少蓝色.比如,要得到车子的亮红色,我们用 color(1,0,0),也就是让海龟用百分之百的红色画笔 ...

  8. ARM mbed平台WIZwiki-W7500使用说明

    ARM mbed IDE 是ARM内核微控制器的在线开发工具,其站点是:http://developer.mbed.org. 站点提供了在线编译器,不须要本地安装编译器就可以进行开发,因此没有地点.时 ...

  9. C# where用法解析

    where 子句用于指定类型约束,这些约束可以作为泛型声明中定义的类型参数的变量.1.接口约束.例如,可以声明一个泛型类 MyGenericClass,这样,类型参数 T 就可以实现 ICompara ...

  10. CSS3 3D立方体翻转菜单实现教程

    今天我们来看一个非常有创意的CSS3 3D菜单,这个菜单的菜单项是可以旋转的长方体,鼠标滑过是长方体即可旋转,看看下面的效果图,是不是感觉非常酷,我觉得这个菜单很适合用在咱们开发人员的个人网站上. 当 ...