获取对象信息
拿到一个对象的引用时,如何知道其类型和有哪些属性、方法?可用以下内置函数。
1. type() —— 判断类型
type(对象)返回对象对应的类(Class)类型。- 基本类型:
type(123)==int,type('abc')==str,type(None)为 NoneType。 - 函数、类实例也可判断:
type(abs),type(a)(Animal 实例)。 - 在 if 中比较:
type(123)==int,type('abc')==str。
判断是否为函数等
- 使用
types模块中的常量:type(fn)==types.FunctionType(自定义函数)type(abs)==types.BuiltinFunctionType(内置函数)type(lambda x:x)==types.LambdaTypetype((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;可传第三参 default:getattr(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。