python里的“__all__ ”作用
轉載:http://python-china.org/t/725
參考:http://www.cnblogs.com/alamZ/p/6943869.html
用 __all__ 暴露接口,這是一種約定
Python 可以在模塊級別暴露接口:
__all__ = ["foo", "bar"]1、提供了哪些是公開接口的約定
不像 Ruby 或者 Java,Python 沒有語言原生的可見性控制,而是靠一套需要大家自覺遵守的”約定“下工作。比如下劃線開頭的應該對外部不可見。同樣,__all__ 也是對于模塊公開接口的一種約定,比起下劃線,__all__ 提供了暴露接口用的”白名單“。一些不以下劃線開頭的變量(比如從其他地方 import 到當前模塊的成員)可以同樣被排除出去。
import os import sys__all__ = ["process_xxx"] # 排除了 `os` 和 `sys`def process_xxx():pass # omit2、控制 from xxx import * 的行為
代碼中當然是不提倡用 from xxx import * 的寫法的,但是在 console 調試的時候圖個方便還是很常見的。如果一個模塊 spam 沒有定義 __all__,執(zhí)行 from spam import * 的時候會將 spam 中非下劃線開頭的成員都導入當前命名空間中,這樣當然就有可能弄臟當前命名空間。如果顯式聲明了 __all__,import * 就只會導入 __all__ 列出的成員。如果 __all__ 定義有誤,列出的成員不存在,還會明確地拋出異常,而不是默默忽略。
3、為 lint 工具提供輔助
編寫一個庫的時候,經常會在 __init__.py 中暴露整個包的 API,而這些 API 的實現可能是在包中其他模塊中定義的。如果我們僅僅這樣寫:
from foo.bar import Spam, Egg一些代碼檢查工具,如 pyflakes 就會報錯,認為 Spam 和 Egg 是 import 了又沒被使用的變量。當然一個可行的方法是把這個警告壓掉:
from foo.bar import Spam, Egg # noqa但是更好的方法是顯式定義 __all__,這樣代碼檢查工具會理解這層意思,就不再報 unused variables 的警告:
from foo.bar import Spam, Egg__all__ = ["Spam", "Egg"]需要注意的是大部分情況下 __all__ 都是一個 list,而不是 tuple 或者其他序列類型。如果寫了其他類型的 __all__,如無意外 pyflakes 等 lint 工具會無法識別出。
4、定義 all 需要注意的地方
- 如上所述,__all__ 應該是 list 類型的
- 不應該動態(tài)生成 __all__,比如使用列表解析式。__all__ 的作用就是定義公開接口,如果不以字面量的形式顯式寫出來,就失去意義了。
- 即使有了 __all__ 也不應該在非臨時代碼中使用 from xxx import * 語法,或者用元編程手段模擬 Ruby 的自動 import。Python 不像 Ruby,沒有 Module 這種成員,模塊就是命名空間隔離的執(zhí)行者。如果打破了這一層,而且引入諸多動態(tài)因素,生產環(huán)境跑的代碼就充滿了不確定性,調試也會非常困難。
- 按照 PEP8 建議的風格,__all__ 應該寫在所有 import 語句下面,和函數、常量等模塊成員定義的上面。
如果一個模塊需要暴露的接口改動頻繁,__all__ 可以這樣定義:
__all__ = ["foo","bar","egg", ]最后多出來的逗號在 Python 中是允許的,也是符合 PEP8 風格的。這樣修改一個接口的暴露就只修改一行,方便版本控制的時候看 diff。
轉載于:https://www.cnblogs.com/shengulong/p/7425088.html
總結
以上是生活随笔為你收集整理的python里的“__all__ ”作用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)事务是什么,以及事务四个特性
- 下一篇: 16-最少回文数组