判断
判断对象类型,有哪些可以使用的方法,之前讲过type() 函数
type()
print(type(123)) print(type('ABC')) print(type(None)) #输出 <class 'int'> <class 'str'> <class 'NoneType'>
如果一个函数指向的是类,或者函数,我们也可以使用type()来判断
def abc(): pass class a(object): pass print(type(abc)) print(type(a)) #输出 <class 'function'> <class 'type'>
调用 types 模块对函数等,进行判断
>>> import types >>> def fn(): ... pass ... >>> type(fn)==types.FunctionType True >>> type(abs)==types.BuiltinFunctionType True >>> type(lambda x: x)==types.LambdaType True >>> type((x for x in range(10)))==types.GeneratorType True
使用isinstance()
对于class的继承关系来说,使用type()
就很不方便。我们要判断class的类型,可以使用isinstance()
函数
之前说了用 isinstance 来判断 继承关系,isinstance还有其他的功能
isinstance() 与 type() 区别:
-
type() 不会认为子类是一种父类类型,不考虑继承关系。
-
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()。
语法
以下是 isinstance() 方法的语法:
isinstance(object, classinfo)
参数
- object -- 实例对象。
- classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组。
返回值
如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。。
实例
以下展示了使用 isinstance 函数的实例:
>>>a = 2 >>> isinstance (a,int) True >>> isinstance (a,str) False >>> isinstance (a,(str,int,list)) # 是元组中的一个返回 True True
type() 与 isinstance()区别:
class A: pass class B(A): pass isinstance(A(), A) # returns True type(A()) == A # returns True isinstance(B(), A) # returns True type(B()) == A # returns False
总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。
使用dir()
描述
如果要获得一个对象的所有属性和方法,可以使用dir()
函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。
语法
dir 语法:
dir([object])
参数说明:
- object -- 对象、变量、类型。
返回值
返回模块的属性列表。
实例
以下实例展示了 dir 的使用方法:
>>>dir() # 获得当前模块的属性列表 ['__builtins__', '__doc__', '__name__', '__package__', 'arr', 'myslice'] >>> dir([ ]) # 查看列表的方法 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] >>>
配合getattr()
、setattr()
以及hasattr()
,我们可以直接操作一个对象的状态:
class Test(object): def __init__(self): self.x = 9 def power(self): return self.x + self.x obj = Test() print(hasattr(obj,'x')) #有属性‘x’ 吗 ? print(hasattr(obj,'y')) #有属性'y' 吗? setattr(obj,'y',10) #设置一个属性y并赋值10 print(getattr(obj,'y'))#获取y 的值 print(obj.y) #打印y的值 #输出 True False 10 10
如何避免获取不存在的值报错的方法
class Test(object): def __init__(self): self.x = 9 def power(self): return self.x + self.x obj = Test() print(getattr(obj,'k')) #如果获取不存在的值,就会抛出AttributeError的错误 #输出 Traceback (most recent call last): File "G:/python练习/网络编程/oop_object_1.py", line 38, in <module> print(getattr(obj,'k')) AttributeError: 'Test' object has no attribute 'k'
可以传入一个default参数,如果获取的属性不存在,就返回默认值
class Test(object): def __init__(self): self.x = 9 def power(self): return self.x + self.x obj = Test() #print(getattr(obj,'k')) #如果获取不存在的值,就会抛出AttributeError的错误 print(getattr(obj,'k',404))#传入default参数 #输出 404
也可以获得对象的方法:
>>> hasattr(obj, 'power') # 有属性'power'吗? True >>> getattr(obj, 'power') # 获取属性'power' <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn >>> fn # fn指向obj.power <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>> >>> 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()
方法返回的是有效的图像数据,就不影响读取图像的功能。