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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章