四個(gè)讓 Python 代碼更容易閱讀的函數(shù)
當(dāng)程序代碼行變多時(shí),閱讀代碼變得困難。即使是一些簡(jiǎn)單的任務(wù)也會(huì)很困難。例如:
- 如何快速查看當(dāng)前腳本的所有變量名和值?
- 如何檢查大型函數(shù)或類的所有變量名稱和值?
- 如何獲取特定對(duì)象的有效屬性列表?
當(dāng)然,我們可以逐行查找代碼并記住名稱或?qū)⑺鼈儗懺诓莞寮堉?。但是,這根本不是高效的,也不輕松。
閱讀代碼比編寫代碼更難。— 喬爾·斯波爾斯基
為了讓我們的生活更輕松,Python 提供了四個(gè)有用的內(nèi)置函數(shù)來幫助我們方便地顯示特定變量名稱和值 。
函數(shù) 1: globals()
顧名思義,該 globals()函數(shù)將顯示全局變量信息 。
例如,如果我們打開 Python 控制臺(tái)并輸入 globals(), 將返回如下結(jié)果:
- Python 3.8.5 (v3.8.5:580fbb018f, Jul 20 2020, 12:11:27)
- [Clang 6.0 (clang-600.0.57)] on darwin
- Type "help", "copyright", "credits" or "license" for more information.
- >>> globals()
- {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>}
- >>>
如果我們添加一個(gè)變量:
- >>> name = 'Python七號(hào)'
- >>> globals()
- {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': 'Python七號(hào)'}
- >>>
由于該 globals()函數(shù)只返回一個(gè)包含全局變量的字典。我們可以操縱這個(gè) dict 來獲取一些我們感興趣的數(shù)據(jù):
- >>> [n for n in globals() if not n.startswith('__')]
- ['name']
- >>>
如上例所示,我們使用列表推導(dǎo)式來獲取所有非雙下劃線的變量名稱。
函數(shù) 2:locals()
了解 globals()之后, locals()函數(shù)就是小菜一碟。顧名思義,它將返回一個(gè)包含所有本地變量和值的字典。
順便說一下,如果我們locals()在全局范圍內(nèi)調(diào)用 ,結(jié)果與 globals()相同。
- >>> globals() == locals()
- True
- >>>
函數(shù) 3:vars()
該 vars()函數(shù)將返回 __dict__,這是一個(gè)用于存儲(chǔ)對(duì)象屬性的字典。其結(jié)果與直接調(diào)用對(duì)象的__dict__方法產(chǎn)生的結(jié)果相同 。
- >>> vars()
- {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': 'Python七號(hào)'}
- >>> class A:
- ... name = 'Python七號(hào)'
- ...
- >>>
- >>> vars(A)
- mappingproxy({'__module__': '__main__', 'name': 'Python七號(hào)', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None})
- >>>
- >>>
不是所有對(duì)象都有 __dict__方法,因此vars()只能在部分對(duì)象中使用。
- >>> num = 1
- >>> vars(num)
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- TypeError: vars() argument must have __dict__ attribute
- >>>
如上例所示, int類型對(duì)象不包含 __dict__,因此如果我們vars()將引發(fā)TypeError 。
函數(shù) 4:dir()
該 dir()函數(shù)幫助顯示模塊或?qū)ο髢?nèi)的名稱列表。
- >>> dir(A)
- ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
- >>> dir(num)
- ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'as_integer_ratio', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
- >>> dir()
- ['A', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'name', 'num']
- >>>
實(shí)際上,該dir方法在 __dir__()內(nèi)部調(diào)用 。
如上所示,如果我們改變 __dir__工作方式,結(jié)果 dir()也會(huì)改變。
其他自省函數(shù)
自省就是自我反省,在編程方面是指程序在運(yùn)行時(shí)自我判斷對(duì)象類型的能力,也可以說是反射,檢查某些事物以確定它是什么、它知道什么以及它能做什么,Django 框架之所以如此靈活,很多 ORM 類都用到了 Python 的自省函數(shù)。
與自省相關(guān)的主要方法:
- hasattr(object, name)檢查對(duì)象是否具體 name 屬性。返回 bool.
- getattr(object, name, default)獲取對(duì)象的name屬性。
- setattr(object, name, default)給對(duì)象設(shè)置name屬性
- delattr(object, name)給對(duì)象刪除name屬性
- isinstance(name, object)檢查name是不是object對(duì)象
- type(object)查看對(duì)象的類型
- callable(object)判斷對(duì)象是否是可調(diào)用對(duì)象
最后
這四個(gè)內(nèi)置函數(shù)是我們顯示名稱和值的有用工具。它們的常見使用場(chǎng)景是在 Python 控制臺(tái)中使用,以在我們閱讀程序時(shí)探索腳本或?qū)ο蟆ytho 的內(nèi)省函數(shù)也可以在運(yùn)行時(shí)動(dòng)態(tài)檢查對(duì)象的類型和方法,可以幫助我們檢查代碼,也方便我們編寫出靈活可擴(kuò)展的程序。
本文轉(zhuǎn)載自微信公眾號(hào)「Python七號(hào)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Python七號(hào)公眾號(hào)。