跳到主要内容

获取对象信息

拿到一个对象的引用时,如何知道其类型有哪些属性、方法?可用以下内置函数。

1. type() —— 判断类型

  • type(对象) 返回对象对应的类(Class)类型
  • 基本类型:type(123)==inttype('abc')==strtype(None) 为 NoneType。
  • 函数、类实例也可判断:type(abs)type(a)(Animal 实例)。
  • if 中比较:type(123)==inttype('abc')==str

判断是否为函数等

  • 使用 types 模块中的常量:
    • type(fn)==types.FunctionType(自定义函数)
    • type(abs)==types.BuiltinFunctionType(内置函数)
    • type(lambda x:x)==types.LambdaType
    • type((x for x in range(10)))==types.GeneratorType(生成器)
import types
type(fn) == types.FunctionType # True

2. isinstance() —— 判断类型(推荐)

  • 有继承关系时type() 不方便(子类实例 type 是子类,不等于父类);用 isinstance(对象, 类) 可判断对象是否是该类型本身,或位于其父继承链上
  • 优先使用 isinstance(),可把指定类型及其所有子类一并判断。
# 继承链:object -> Animal -> Dog -> Husky
h = Husky()
isinstance(h, Husky) # True
isinstance(h, Dog) # True
isinstance(h, Animal) # True

d = Dog()
isinstance(d, Husky) # False
  • 基本类型也可用:isinstance('a', str)isinstance(123, int)
  • 判断是否属于多种类型之一isinstance([1,2,3], (list, tuple)) → True。

3. dir() —— 列出属性和方法

  • dir(对象) 返回一个字符串 list,包含对象的所有属性和方法名(含特殊方法 __xxx__)。
  • __len__:返回长度;len(对象) 内部会调用对象的 __len__(),故 len('ABC')'ABC'.__len__() 等价。
  • 自定义类若想被 len(myObj) 调用,需实现 __len__() 方法。其余为普通属性或方法(如 lower())。
dir('ABC')   # ['__add__', '__class__', ..., 'capitalize', 'lower', ...]

class MyDog(object):
def __len__(self):
return 100
len(MyDog()) # 100

4. getattr / setattr / hasattr —— 操作属性

  • hasattr(obj, 'attr名'):对象是否有该属性(或方法)。
  • getattr(obj, 'attr名')获取属性;不存在会 AttributeError;可传第三参 defaultgetattr(obj, 'z', 404) 不存在时返回 404。
  • setattr(obj, 'attr名', 值)设置属性。
  • 也可用于方法getattr(obj, 'power') 得到 bound method,赋值给变量后调用等价于 obj.power()
hasattr(obj, 'x')    # True
getattr(obj, 'x') # 9
getattr(obj, 'z', 404) # 不存在时返回 404
setattr(obj, 'y', 19)

fn = getattr(obj, 'power')
fn() # 与 obj.power() 等价

5. 使用原则与示例

  • 只有在不确定对象信息时才用这些函数;能直接写 obj.x 就不要写 getattr(obj, 'x')
  • 典型用法:先判断再调用。例如从“文件流”读图像时,先判断是否有 read 方法(鸭子类型),有再读:
def readImage(fp):
if hasattr(fp, 'read'):
return readData(fp)
return None
  • 在动态语言中,有 read() 不代表一定是文件流,也可能是网络流、内存流等;只要 read() 返回有效数据即可(鸭子类型)。

小结

函数作用
type(x)返回 x 的类型(类);继承场景下不如 isinstance 方便
isinstance(x, A)x 是否为 A 或其子类优先使用;可传元组 isinstance(x, (list, tuple))
dir(x)列出 x 的所有属性、方法名(含 __len__ 等)
hasattr(x, 'name')是否有该属性/方法
getattr(x, 'name', default)获取属性/方法;无则 AttributeError 或返回 default
setattr(x, 'name', val)设置属性

记忆:类型用 isinstance;列名字用 dir;有没有用 hasattr,拿/设用 getattr/setattr;能直接访问就别用 getattr。