Python中获取对象信息的方法


Posted in Python onApril 27, 2015

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
使用type()

首先,我们来判断对象类型,使用type()函数:

基本类型都可以用type()判断:

>>> type(123)
<type 'int'>
>>> type('str')
<type 'str'>
>>> type(None)
<type 'NoneType'>

如果一个变量指向函数或者类,也可以用type()判断:

>>> type(abs)
<type 'builtin_function_or_method'>
>>> type(a)
<class '__main__.Animal'>

但是type()函数返回的是什么类型呢?它返回type类型。如果我们要在if语句中判断,就需要比较两个变量的type类型是否相同:

>>> type(123)==type(456)
True
>>> type('abc')==type('123')
True
>>> type('abc')==type(123)
False

但是这种写法太麻烦,Python把每种type类型都定义好了常量,放在types模块里,使用之前,需要先导入:

>>> import types
>>> type('abc')==types.StringType
True
>>> type(u'abc')==types.UnicodeType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType
True

最后注意到有一种类型就叫TypeType,所有类型本身的类型就是TypeType,比如:

>>> type(int)==type(str)==types.TypeType
True

使用isinstance()

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数。

我们回顾上次的例子,如果继承关系是:

object -> Animal -> Dog -> Husky

那么,isinstance()就可以告诉我们,一个对象是否是某种类型。先创建3种类型的对象:

>>> a = Animal()
>>> d = Dog()
>>> h = Husky()

然后,判断:

>>> isinstance(h, Husky)
True

没有问题,因为h变量指向的就是Husky对象。

再判断:

>>> isinstance(h, Dog)
True

h虽然自身是Husky类型,但由于Husky是从Dog继承下来的,所以,h也还是Dog类型。换句话说,isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。

因此,我们可以确信,h还是Animal类型:

>>> isinstance(h, Animal)
True

同理,实际类型是Dog的d也是Animal类型:

>>> isinstance(d, Dog) and isinstance(d, Animal)
True

但是,d不是Husky类型:

能用type()判断的基本类型也可以用isinstance()判断:

>>> isinstance('a', str)
True
>>> isinstance(u'a', unicode)
True
>>> isinstance('a', unicode)
False

并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是str或者unicode:

>>> isinstance('a', (str, unicode))
True
>>> isinstance(u'a', (str, unicode))
True

由于str和unicode都是从basestring继承下来的,所以,还可以把上面的代码简化为:

>>> isinstance(u'a', basestring)
True

使用dir()

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

>>> dir('ABC')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

我们自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法:

>>> class MyObject(object):
...   def __len__(self):
...     return 100
...
>>> obj = MyObject()
>>> len(obj)
100

剩下的都是普通属性或方法,比如lower()返回小写的字符串:

>>> 'ABC'.lower()
'abc'

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

>>> class MyObject(object):
...   def __init__(self):
...     self.x = 9
...   def power(self):
...     return self.x * self.x
...
>>> obj = MyObject()

紧接着,可以测试该对象的属性:

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

如果试图获取不存在的属性,会抛出AttributeError的错误:

可以传入一个default参数,如果属性不存在,就返回默认值:

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404

也可以获得对象的方法:

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

小结

通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。如果可以直接写:

sum = obj.x + obj.y

就不要写:

sum = getattr(obj, 'x') + getattr(obj, 'y')

一个正确的用法的例子如下:

def readImage(fp):
  if hasattr(fp, 'read'):
    return readData(fp)
  return None

假设我们希望从文件流fp中读取图像,我们首先要判断该fp对象是否存在read方法,如果存在,则该对象是一个流,如果不存在,则无法读取。hasattr()就派上了用场。

请注意,在Python这类动态语言中,有read()方法,不代表该fp对象就是一个文件流,它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。

Python 相关文章推荐
Python数据结构之顺序表的实现代码示例
Nov 15 Python
Python Socket使用实例
Dec 18 Python
python利用requests库进行接口测试的方法详解
Jul 06 Python
详解Django中间件执行顺序
Jul 16 Python
python集合比较(交集,并集,差集)方法详解
Sep 13 Python
python保存二维数组到txt文件中的方法
Nov 15 Python
python使用openCV遍历文件夹里所有视频文件并保存成图片
Jan 14 Python
在python中实现求输出1-3+5-7+9-......101的和
Apr 02 Python
Django通过json格式收集主机信息
May 29 Python
pytorch 限制GPU使用效率详解(计算效率)
Jun 27 Python
Scrapy+Selenium自动获取cookie爬取网易云音乐个人喜爱歌单
Feb 01 Python
Python matplotlib 利用随机函数生成变化图形
Apr 26 Python
用实例解释Python中的继承和多态的概念
Apr 27 #Python
Python中设置变量访问权限的方法
Apr 27 #Python
理解Python中的类与实例
Apr 27 #Python
简述Python中的面向对象编程的概念
Apr 27 #Python
介绍Python中的__future__模块
Apr 27 #Python
在Python中使用第三方模块的教程
Apr 27 #Python
在Python中使用模块的教程
Apr 27 #Python
You might like
VFP与其他应用程序的集成
2006/10/09 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
php静态成员方法和静态的成员属性的使用方法
2017/10/26 PHP
ThinkPHP框架实现导出excel数据的方法示例【基于PHPExcel】
2018/05/12 PHP
扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
2011/12/08 Javascript
jQuery对下拉框,单选框,多选框的操作
2014/02/21 Javascript
js数组与字符串的相互转换方法
2014/07/09 Javascript
JavaScript判断是否为数字的4种方法及效率比较
2015/04/01 Javascript
js实现可折叠展开的手风琴菜单效果
2015/09/07 Javascript
JavaScript的removeChild()函数用法详解
2015/12/27 Javascript
BootStrap智能表单实战系列(六)表单编辑页面的数据绑定
2016/06/13 Javascript
Highcharts入门之基本属性
2016/08/02 Javascript
AngularJS入门示例之Hello World详解
2017/01/04 Javascript
微信小程序中顶部导航栏的实现代码
2017/03/30 Javascript
详解Angular操作cookies方法
2018/06/01 Javascript
vue拖拽组件使用方法详解
2018/12/01 Javascript
Vue自定义指令上报Google Analytics事件统计的方法
2019/02/25 Javascript
vue项目打包后怎样优雅的解决跨域
2019/05/26 Javascript
[02:46]解说DC:感谢430陪伴我们的DOTA2国际邀请赛岁月
2016/06/29 DOTA
[54:57]DOTA2-DPC中国联赛定级赛 Aster vs DLG BO3第二场 1月8日
2021/03/11 DOTA
用实例说明python的*args和**kwargs用法
2013/11/01 Python
python后端接收前端回传的文件方法
2019/01/02 Python
详解python 模拟豆瓣登录(豆瓣6.0)
2019/04/18 Python
详谈tensorflow gfile文件的用法
2020/02/05 Python
Linux安装Python3如何和系统自带的Python2并存
2020/07/23 Python
使用 HTML5 Canvas 制作水波纹效果点击图片就会触发
2014/09/15 HTML / CSS
分享29个基于Bootstrap的HTML5响应式网页设计模板
2015/11/19 HTML / CSS
伦敦一家西班牙童装精品店:La Coqueta
2018/02/02 全球购物
瑞士网球商店:Tennis-Point
2020/03/12 全球购物
yy婚礼主持词
2014/03/14 职场文书
2014年小学安全工作总结
2014/12/04 职场文书
无保留意见审计报告
2015/06/05 职场文书
2015年六年级班主任工作总结
2015/10/15 职场文书
教师廉政准则心得体会
2016/01/20 职场文书
品德与社会教学反思
2016/02/24 职场文书
如何用python清洗文件中的数据
2021/06/18 Python