自省,在我們日常生活中,通常是自我反省的意思。
但在計算機編程中,自省並不是這個意思,它的英文單詞是 introspection,表示的是自我檢查的行為或能力。
它的內容包括
- 告訴別人,我是誰
- 告訴別人,我能做什么
(有點面試的感覺了)
Python 是一門動態語言,有了自省,就能讓程序在運行時能夠獲知對象的類型以及該對象下有哪些方法等。
1. 學習 Python 模塊的入口
help()
在 console 模式下,輸入 help() ,可以看到輸出了一段幫助文檔,教你如何使用這個 help,當你看到提示符變成了 help> 時,這時候就進入了 help 模式。

此時你可以鍵入你想要了解的模塊、語法等,help 告訴你如何使用。
比如我輸入 keywords ,就可以看到 Python 里所有的關鍵字。再輸入 modules 就可以查看 Python 中所有的內置模塊。

輸入 modules + 指定包名,就可以查看這個包下有哪些模塊

如果你想學習某個包要如何使用,可以直接在 help 模式下輸入 包名,就像下面這樣,我就可以獲得一份 json 的幫助文檔。

如果你想學習某個關鍵字的用法,可以在 help 模式下直接鍵入 關鍵字 查詢用法,比如我直接鍵入 for 。

查完后,使用 quit 就可以退出 help 模式了。

如果你覺得進入 help 模式太麻煩,可以在 console 模式下直接查詢
>>> help("json")
dir()
dir() 函數可能是 Python 自省機制中最著名的部分了。它返回傳遞給它的任何對象的屬性名稱經過排序的列表。如果不指定對象,則 dir() 返回當前作用域中的名稱。讓我們將 dir() 函數應用於 keyword 模塊,並觀察它揭示了什么:

2. 應用到實際開發中
type()
type() 函數有助於我們確定對象是字符串還是整數,或是其它類型的對象。它通過返回類型對象來做到這一點,可以將這個類型對象與 types 模塊中定義的類型相比較:
>>> type(42)
<class 'int'>
>>> type([])
<class 'list'>
hasattr()
使用 dir() 函數會返回一個對象的屬性列表。
但是,有時我們只想測試一個或多個屬性是否存在。如果對象具有我們正在考慮的屬性,那么通常希望只檢索該屬性。這個任務可以由 hasattr() 來完成.
>>> import json
>>> hasattr(json, "dumps")
True
>>>
getattr()
使用 hasattr 獲知了對象擁有某個屬性后,可以搭配 getattr() 函數來獲取其屬性值。
>>> getattr(json, "__path__")
['/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json']
>>>
使用 getattr 獲取函數后,可以很方便地使用這個函數,比如下面這樣,可以不再使寫 json.dumps 這么字。
>>> dumps = getattr(json, "dumps")
>>> dumps({"name": "MING"})
'{"name": "MING"}'
>>>
# 當然你還有更簡單的方法
>>> mydumps = json.dumps
>>> mydumps({"name": "MING"})
'{"name": "MING"}'
id()
id() 函數返回對象的唯一標識符,標識符是一個整數。
>>> a = "hello"
>>> b = "world"
>>>
>>> id(a)
4470767944
>>> id(b)
4499487408
>>>
isinstance()
使用 isinstance() 函數可以確定一個對象是否是某個特定類型或定制類的實例。
>>> isinstance("python", str)
True
>>> isinstance(10, int)
True
>>> isinstance(False, bool)
True
callable()
使用 callable 可以確定一個對象是否是可調用的,比如函數,類這些對象都是可以調用的對象。
>>> callable("hello")
False
>>>
>>> callable(str)
True
>>>
3. 模塊(Modules)
_doc_
使用 __doc__ 這個魔法方法,可以查詢該模塊的文檔,它輸出的內容和 help() 一樣。

_name_
始終是定義時的模塊名;即使你使用import .. as 為它取了別名,或是賦值給了另一個變量名。
>>> import json
>>> json.__name__
'json'
>>>
>>> import json as js
>>> js.__name__
'json'
_file_
包含了該模塊的文件路徑。需要注意的是內建的模塊沒有這個屬性,訪問它會拋出異常!
>>> import json
>>> json.__file__
'/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/__init__.py'
_dict_
包含了模塊里可用的屬性名-屬性的字典;也就是可以使用模塊名.屬性名訪問的對象。
4. 類(Class)
_doc_
文檔字符串。如果類沒有文檔,這個值是None。
>>> class People:
... '''
... people class
... '''
...
>>> p = People()
>>>
>>> print(p.__doc__)
people class
>>>
_name_
始終是定義時的類名。
>>> People.__name__
'People'
_dict_
包含了類里可用的屬性名-屬性的字典;也就是可以使用類名.屬性名訪問的對象。
>>> People.__dict__
mappingproxy({'__module__': '__main__', '__doc__': '\n people class\n ', '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>})
_module_
包含該類的定義的模塊名;需要注意,是字符串形式的模塊名而不是模塊對象。
由於我是在 交互式命令行的環境下,所以模塊是 __main__
>>> People.__module__
'__main__'
如果將上面的代碼放入 demo.py,並且從 people 模塊導入 People 類,其值就是 people 模塊

_bases_
直接父類對象的元組;但不包含繼承樹更上層的其他類,比如父類的父類。
>>> class People: pass
...
>>> class Teenager: pass
...
>>> class Student(Teenager): pass
...
>>> Student.__bases__
(<class '__main__.Teenager'>,)
>>>
文末福利
本人原創的 《PyCharm 中文指南》一書前段時間一經發布,就火爆了整個 Python 圈,發布僅一天的時間,下載量就突破了 1000 ,並且在當天就在 Github 上就收獲了數百的 star,截至目前,下載量已經破萬。
這本書一共將近 200 頁,內含大量的圖解,制作之精良,值得每個 Python 工程師 人手一份。

為方便你下載,我將這本書上傳到 百度網盤上了,你可以自行獲取。
鏈接:https://pan.baidu.com/s/1-NzATHFtaTV1MQzek70iUQ
密碼:mft3
