Python对象自省——运行时判断对象的类型

简介

自省(introspection)指在运行时判断一个对象的类型

Python中一切都是对象,自省是Python的强项

通过自省可以知道一个对象的能力、状态




type()

type()返回对象类型

a = list()
print(type(a))
# <class 'list'>




dir()

dir()是自省的一个重要函数,返回列表,列出对象所拥有的属性和方法

a = list()
print(dir(a))
# ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', 
# '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', 
# '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__',
# '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__',
# '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__',
# '__setitem__', '__sizeof__', '__str__', '__subclasshook__',
# 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']




pdir()

直接用dir()看上去非常杂乱,使用pdir()可以美化输出

安装

pip install pdir2

代码

import pdir

a = list()
print(pdir(a))

在这里插入图片描述




inspect模块

Python标准库中的inspect模块用于获取对象的信息,主要的功能有:

  • 类型检查
  • 获取源码
  • 检查类与函数
  • 检查解释器调用堆栈

查看该模块的函数及其含义:

import pdir
import inspect

print(pdir(inspect))
'''
property:
    ......
module attribute:
    ......
special attribute:
    ......
class:
    ......
function:
    ......
    getmembers: Return all members of an object as (name, value) pairs sorted by name.
    getdoc: Get the documentation string for an object.
    getmodule: Return the module an object was defined in, or None if not found.
    getfile: Work out which source or compiled file an object was defined in.
    getsourcefile: Return the filename that can be used to locate an object's source.
    getsource: Return the text of the source code for an object.
    signature: Get a signature object for the passed callable.
    getclasstree: Arrange the given list of classes into a hierarchy of nested lists.
    getfullargspec: Get the names and default values of a callable object's parameters.
    formatargspec: Format an argument spec from the values returned by getfullargspec.
    getcallargs: Get the mapping of arguments to values.
    getattr_static: Retrieve attributes without triggering dynamic lookup via the
	......
exception:
    EndOfBlock: Common base class for all non-exit exceptions.
'''




getmembers() 返回对象成员信息

getmembers() 以键值对列表的形式返回对象所有成员信息

is开头的函数名可作为 getmembers() 的第2个参数

from inspect import *

a = [1, 2, 3]
print(getmembers(a))
print(getmembers(a, isclass))  # 返回类型
print(getmembers(a, isbuiltin))  # 返回内置函数


# [('__add__', <method-wrapper '__add__' of list object at 0x0000000009F9BA88>), ('__class__', <class 'list'>), ('__contains__', <method-wrapper '__contains__' of list object at 0x0000000009F9BA88>), ('__delattr__', <method-wrapper '__delattr__' of list object at 0x0000000009F9BA88>), ('__delitem__', <method-wrapper '__delitem__' of list object at 0x0000000009F9BA88>), ('__dir__', <built-in method __dir__ of list object at 0x0000000009F9BA88>), ('__doc__', "list() -> new empty list\nlist(iterable) -> new list initialized from iterable's items"), ('__eq__', <method-wrapper '__eq__' of list object at 0x0000000009F9BA88>), ('__format__', <built-in method __format__ of list object at 0x0000000009F9BA88>), ('__ge__', <method-wrapper '__ge__' of list object at 0x0000000009F9BA88>), ('__getattribute__', <method-wrapper '__getattribute__' of list object at 0x0000000009F9BA88>), ('__getitem__', <built-in method __getitem__ of list object at 0x0000000009F9BA88>), ('__gt__', <method-wrapper '__gt__' of list object at 0x0000000009F9BA88>), ('__hash__', None), ('__iadd__', <method-wrapper '__iadd__' of list object at 0x0000000009F9BA88>), ('__imul__', <method-wrapper '__imul__' of list object at 0x0000000009F9BA88>), ('__init__', <method-wrapper '__init__' of list object at 0x0000000009F9BA88>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x000000006B869530>), ('__iter__', <method-wrapper '__iter__' of list object at 0x0000000009F9BA88>), ('__le__', <method-wrapper '__le__' of list object at 0x0000000009F9BA88>), ('__len__', <method-wrapper '__len__' of list object at 0x0000000009F9BA88>), ('__lt__', <method-wrapper '__lt__' of list object at 0x0000000009F9BA88>), ('__mul__', <method-wrapper '__mul__' of list object at 0x0000000009F9BA88>), ('__ne__', <method-wrapper '__ne__' of list object at 0x0000000009F9BA88>), ('__new__', <built-in method __new__ of type object at 0x000000006B869530>), ('__reduce__', <built-in method __reduce__ of list object at 0x0000000009F9BA88>), ('__reduce_ex__', <built-in method __reduce_ex__ of list object at 0x0000000009F9BA88>), ('__repr__', <method-wrapper '__repr__' of list object at 0x0000000009F9BA88>), ('__reversed__', <built-in method __reversed__ of list object at 0x0000000009F9BA88>), ('__rmul__', <method-wrapper '__rmul__' of list object at 0x0000000009F9BA88>), ('__setattr__', <method-wrapper '__setattr__' of list object at 0x0000000009F9BA88>), ('__setitem__', <method-wrapper '__setitem__' of list object at 0x0000000009F9BA88>), ('__sizeof__', <built-in method __sizeof__ of list object at 0x0000000009F9BA88>), ('__str__', <method-wrapper '__str__' of list object at 0x0000000009F9BA88>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x000000006B869530>), ('append', <built-in method append of list object at 0x0000000009F9BA88>), ('clear', <built-in method clear of list object at 0x0000000009F9BA88>), ('copy', <built-in method copy of list object at 0x0000000009F9BA88>), ('count', <built-in method count of list object at 0x0000000009F9BA88>), ('extend', <built-in method extend of list object at 0x0000000009F9BA88>), ('index', <built-in method index of list object at 0x0000000009F9BA88>), ('insert', <built-in method insert of list object at 0x0000000009F9BA88>), ('pop', <built-in method pop of list object at 0x0000000009F9BA88>), ('remove', <built-in method remove of list object at 0x0000000009F9BA88>), ('reverse', <built-in method reverse of list object at 0x0000000009F9BA88>), ('sort', <built-in method sort of list object at 0x0000000009F9BA88>)]
# [('__class__', <class 'list'>)]
# [('__dir__', <built-in method __dir__ of list object at 0x0000000009F9BA88>), ('__format__', <built-in method __format__ of list object at 0x0000000009F9BA88>), ('__getitem__', <built-in method __getitem__ of list object at 0x0000000009F9BA88>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x000000006B869530>), ('__new__', <built-in method __new__ of type object at 0x000000006B869530>), ('__reduce__', <built-in method __reduce__ of list object at 0x0000000009F9BA88>), ('__reduce_ex__', <built-in method __reduce_ex__ of list object at 0x0000000009F9BA88>), ('__reversed__', <built-in method __reversed__ of list object at 0x0000000009F9BA88>), ('__sizeof__', <built-in method __sizeof__ of list object at 0x0000000009F9BA88>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x000000006B869530>), ('append', <built-in method append of list object at 0x0000000009F9BA88>), ('clear', <built-in method clear of list object at 0x0000000009F9BA88>), ('copy', <built-in method copy of list object at 0x0000000009F9BA88>), ('count', <built-in method count of list object at 0x0000000009F9BA88>), ('extend', <built-in method extend of list object at 0x0000000009F9BA88>), ('index', <built-in method index of list object at 0x0000000009F9BA88>), ('insert', <built-in method insert of list object at 0x0000000009F9BA88>), ('pop', <built-in method pop of list object at 0x0000000009F9BA88>), ('remove', <built-in method remove of list object at 0x0000000009F9BA88>), ('reverse', <built-in method reverse of list object at 0x0000000009F9BA88>), ('sort', <built-in method sort of list object at 0x0000000009F9BA88>)]


class T:
    def f(self):
        pass


print(getmembers(T(), isbuiltin))
print(getmembers(T(), isroutine))  # 返回内置函数,包括用户自定义
# [('__dir__', <built-in method __dir__ of T object at 0x0000000009F90EF0>), ('__format__', <built-in method __format__ of T object at 0x0000000009F90EF0>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x0000000009AFDE78>), ('__new__', <built-in method __new__ of type object at 0x000000006B86C5C0>), ('__reduce__', <built-in method __reduce__ of T object at 0x0000000009F90EF0>), ('__reduce_ex__', <built-in method __reduce_ex__ of T object at 0x0000000009F90EF0>), ('__sizeof__', <built-in method __sizeof__ of T object at 0x0000000009F90EF0>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x0000000009AFDE78>)]
# [('__dir__', <built-in method __dir__ of T object at 0x0000000009F90EF0>), ('__format__', <built-in method __format__ of T object at 0x0000000009F90EF0>), ('__init_subclass__', <built-in method __init_subclass__ of type object at 0x0000000009AFDE78>), ('__new__', <built-in method __new__ of type object at 0x000000006B86C5C0>), ('__reduce__', <built-in method __reduce__ of T object at 0x0000000009F90EF0>), ('__reduce_ex__', <built-in method __reduce_ex__ of T object at 0x0000000009F90EF0>), ('__sizeof__', <built-in method __sizeof__ of T object at 0x0000000009F90EF0>), ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x0000000009AFDE78>), ('f', <bound method T.f of <__main__.T object at 0x0000000009F90EF0>>)]




获取源码

getdoc():获取文档

getmodule():获取所属模块

getfile():获取定义对象的文件的名称

getsourcefile():获取定义对象的源文件

getsource():获取源代码

import requests
from inspect import *
from collections import defaultdict

a = [1, 2, 3]
print(getdoc(list))  # list初始化的文档
print(getdoc(list.append))  # list.append()的文档
# list() -> new empty list
# list(iterable) -> new list initialized from iterable's items
# L.append(object) -> None -- append object to end

print(getmodule(defaultdict))  # 所属模块
# <module 'collections' from 'C:\\Users\\Administrator\\AppData\\Local\\Programs\\Python\\Python36\\lib\\collections\\__init__.py'>

print(getfile(requests))  # 定义对象的文件的名称
print(getsourcefile(requests))  # 定义对象的源文件
# C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\site-packages\requests\__init__.py
# C:\Users\Administrator\AppData\Local\Programs\Python\Python36\lib\site-packages\requests\__init__.py


def f():
    print('Hello World!')


print(getsource(f))  # 源代码
# def f():
#     print('Hello World!')




利用签名对象自省

使用signature()构建签名对象进行自省,获取参数列表

更多方法查阅inspect.Signature

from inspect import signature


def foo(a, *, b: int, **kwargs):
    pass


sig = signature(foo)
print(sig)  # 参数列表
print(sig.parameters['b'])  # 参数b的类型
print(sig.parameters['b'].annotation)  # 参数b的类型标注
# (a, *, b:int, **kwargs)
# b:int
# <class 'int'>




类与函数

getclasstree():返回类的继承关系

from inspect import *
from collections import OrderedDict

d = OrderedDict()
classes = getmembers(d, isclass)  # 返回类型
print(classes)
classes = [cls[1] for cls in classes]  # 组装
print(classes)
tree = getclasstree(classes)  # 返回类的继承关系
print(tree)
# [('__class__', <class 'collections.OrderedDict'>)]
# [<class 'collections.OrderedDict'>]
# [(<class 'dict'>, (<class 'object'>,)), [(<class 'collections.OrderedDict'>, (<class 'dict'>,))]]

getfullargspec():获取完整参数信息

from inspect import *


def f(a: int, b: float):
    pass


print(formatargspec(*getfullargspec(f)))
# (a: int, b: float)

getcallargs():获取调用参数

from inspect import *


def f(a, b=1, *pos, **named):
    pass


print(getcallargs(f, 1, 2, 3))
print(getcallargs(f, a=2, x=4))
try:
    getcallargs(f)
except Exception as e:
    print(e)
# {'a': 1, 'b': 2, 'pos': (3,), 'named': {}}
# {'pos': (), 'named': {'x': 4}, 'a': 2, 'b': 1}
# f() missing 1 required positional argument: 'a'




解释器堆栈

更多内容查阅解释器堆栈

from inspect import *

print(getframeinfo(currentframe()))
# Traceback(filename='D:/code/test/test.py', lineno=4, function='<module>', code_context=['print(getframeinfo(currentframe()))\n'], index=0)




获取静态属性

import math
from inspect import *


class T:
    pi = 3.14


print(getattr_static(T, 'pi'))
print(getattr_static(math, 'pi'))
# 3.14
# 3.141592653589793




参考文献

  1. 对象自省 - Python进阶
  2. inspect — Inspect live objects — Python 3.8.3 documentation
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章