当拿到一个对象的引用时,如何来判断这个对象是什么类型?有哪些方法呢?
接下来我们一起来详细学习一下吧!
第一种方法:使用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)andisinstance(d,Animal)True
但是,d不是Husky类型:
isinstance(d,Husky)False
能用type()判断的基本类型也可以用isinstance()判断:
isinstance(a,str)Trueisinstance(ua,unicode)Trueisinstance(a,unicode)False
并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是str或者unicode:
isinstance(a,(str,unicode))Trueisinstance(ua,(str,unicode))True
由于str和unicode都是从basestring继承下来的,所以,还可以把上面的代码简化为:
isinstance(ua,basestring)True
第二种方法:使用type()
想要判断对象类型还有一种方法就是使用type()函数。
基本类型都可以用type()函数来判断:
type()typeinttype(str)typestrtype(None)typeNoneType
一个变量指向函数或者类,也可以用type()判断:
type(abs)typebuiltin_function_or_methodtype(a)class__main__.Animal
但是type()函数返回的是什么类型呢?
它返回type类型。
如果要在if语句中判断,就需要比较两个变量的type类型是否相同:
type()==type()Truetype(abc)==type()Truetype(abc)==type()False
但是这种写法太麻烦,Python把每种type类型都定义好了常量,放在types模块里,使用之前,需要先导入:
importtypestype(abc)==types.StringTypeTruetype(uabc)==types.UnicodeTypeTruetype([])==types.ListTypeTruetype(str)==types.TypeTypeTrue
最后注意到有一种类型就叫TypeType,所有类型本身的类型就是TypeType,比如:
type(int)==type(str)==types.TypeTypeTrue
第三种方法:判断基本数据类型可以直接写int,str等。
但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:
importtypesdeffn():...pass...type(fn)==types.FunctionTypeTruetype(abs)==types.BuiltinFunctionTypeTruetype(lambdax:x)==types.LambdaTypeTruetype((xforxinrange(10)))==types.GeneratorTypeTrue
第四种方法:使用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)3ABC.__len__()3
自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法:
classMyObject(object):...def__len__(self):...return...obj=MyObject()len(obj)
剩下的都是普通属性或方法,比如lower()返回小写的字符串:
ABC.lower()abc
仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),可以直接操作一个对象的状态:
classMyObject(object):...def__init__(self):...self.x=9...defpower(self):...returnself.x*self.x...obj=MyObject()
然后测试该对象的属性:
hasattr(obj,x)#有属性x吗?Trueobj.x9hasattr(obj,y)#有属性y吗?Falsesetattr(obj,y,19)#设置一个属性yhasattr(obj,y)#有属性y吗?Truegetattr(obj,y)#获取属性y19obj.y#获取属性y19
如果试图获取不存在的属性,会抛出AttributeError的错误:
getattr(obj,z)#获取属性zTraceback(mostrecentcalllast):File"stdin",line1,inmoduleAttributeError:MyObjectobjecthasnoattributez
可以传入一个default参数,如果属性不存在,就返回默认值:
getattr(obj,z,)#获取属性z,如果不存在,返回默认值
也可以获得对象的方法:
hasattr(obj,power)#有属性power吗?Truegetattr(obj,power)#获取属性powerboundmethodMyObject.powerof__main__.MyObjectobjectat0xca35d0fn=getattr(obj,power)#获取属性power并赋值到变量fnfn#fn指向obj.powerboundmethodMyObject.powerof__main__.MyObjectobjectat0xca35d0fn()#调用fn()与调用obj.power()是一样的81
通过内置的一系列函数,可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,才会去获取对象信息。如果可以直接写:
sum=obj.x+obj.y
就不要写:
sum=getattr(obj,x)+getattr(obj,y)
一个正确的用法的例子如下:
defreadImage(fp):ifhasattr(fp,read):returnreadData(fp)returnNone
如果想要从文件流fp中读取图像,首先就要先判断这个fp对象是否存在read方法。
如果存在,则该对象是一个流。
如果不存在,则无法读取。
这时候hasattr()就派上了用场。
请注意:
在Python这类动态语言中,有read()方法,不代表该fp对象就是一个文件流。
它也可能是网络流,也可能是内存中的一个字节流,但只要read()方法返回的是有效的图像数据,就不影响读取图像的功能。
实例属性和类属性
由于Python是动态语言,根据类创建的实例可以任意绑定属性。给实例绑定属性的方法是通过实例变量,或者通过self变量:
classStudent(object):def__init__(self,name):self.name=names=Student(Bob)s.score=90
但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:
classStudent(object):name=‘Student’
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:
classStudent(object):...name=Student...s=Student()#创建实例sprint(s.name)#打印name属性,因为实例并没有name属性,所以会继续查找class的name属性Studentprint(Student.name)#打印类的name属性Students.name=Michael#给实例绑定name属性print(s.name)#由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性Michaelprint(Student.name)#但是类属性并未消失,用Student.name仍然可以访问Studentdels.name#如果删除实例的name属性#注意删除delprint(s.name)#再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了Student
从上面的例子可以看出,在编写程序的时候,千万不要对实例属性和类属性使用相同的名字。
因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。
以上即为对于Python对象的信息获取方法介绍,大家按照以上的案例进行实际操作一下,如果在学习过程中遇到其他相关问题欢迎下方留言。
想要自学Python的同学,为大家推荐千锋原创教材《Python基础入门》:
Python基础入门教程:Python面向对象的概念
-06-23
Python基础入门教程:面向对象编程与面向过程编程语言对比
-06-23
Python基础入门教程:对象与类的区别
-06-23
Python基础入门教程:类的定义
-06-23
Python基础入门教程:Python中的生成器
-06-22
预览时标签不可点收录于话题#个上一篇下一篇