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

简介

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

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

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




type()

type()返回对象类型

a = list()
print(type(a))
# 




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))

Python对象自省——运行时判断对象的类型_第1张图片




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__', ), ('__class__', ), ('__contains__', ), ('__delattr__', ), ('__delitem__', ), ('__dir__', ), ('__doc__', "list() -> new empty list\nlist(iterable) -> new list initialized from iterable's items"), ('__eq__', ), ('__format__', ), ('__ge__', ), ('__getattribute__', ), ('__getitem__', ), ('__gt__', ), ('__hash__', None), ('__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', )]
# [('__class__', )]
# [('__dir__', ), ('__format__', ), ('__getitem__', ), ('__init_subclass__', ), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__reversed__', ), ('__sizeof__', ), ('__subclasshook__', ), ('append', ), ('clear', ), ('copy', ), ('count', ), ('extend', ), ('index', ), ('insert', ), ('pop', ), ('remove', ), ('reverse', ), ('sort', )]


class T:
    def f(self):
        pass


print(getmembers(T(), isbuiltin))
print(getmembers(T(), isroutine))  # 返回内置函数,包括用户自定义
# [('__dir__', ), ('__format__', ), ('__init_subclass__', ), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__sizeof__', ), ('__subclasshook__', )]
# [('__dir__', ), ('__format__', ), ('__init_subclass__', ), ('__new__', ), ('__reduce__', ), ('__reduce_ex__', ), ('__sizeof__', ), ('__subclasshook__', ), ('f', >)]




获取源码

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))  # 所属模块
# 

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
# 




类与函数

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__', )]
# []
# [(, (,)), [(, (,))]]

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='', 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

你可能感兴趣的:(Python)