在編寫Python代碼的過程當中,爲了更好的管理代碼,咱們會使用到包(package)、模塊(module)、類(class)、函數(function)。
介紹一下這幾個概念:python
而後再來看看咱們平常使用包、模塊和類的作法app
# 目錄結構 #|--demo.py #|--package_a # |--__init__.py # |--class_a.py 類ClassA # |--class_b.py 類ClassB # ./demo.py # 導入方式一 from package_a.class_a import ClassA from package_a.class_a import ClassB a = ClassA() b = ClassB() # 導入方式二 import package_a.class_a as ca import package_a.class_b as cb a = ca.ClassA() b = cb.ClassB()
好的,咱們的問題來了,怎麼樣才能減小咱們導入部分的代碼呢?或者說怎麼樣才能使得一些相關聯的模塊不須要一個一個的進行導入呢?最終實現到下面的樣子是否是會更好函數
# ./demo.py from package_a import * a = ClassA() b = ClassB()
# ./common.py import sys _packet_ = {} # 裝飾器,func是類或者函數 def export(func): module = sys.modules[func.__module__] # 獲取func的模塊對象 package = sys.modules[module.__package__] # 由模塊對象獲得包對象 package.__dict__[func.__name__] = func # 把func添加到包的__dict__裏 # 生成全部使用該解決方案的包的__all__變量,並把導出的func添加進去 if not package.__name__ in _packet_: _packet_[package.__name__] = [] _packet_[package.__name__].append(func.__name__) # 原封不動地把func返回 return func # 在包的__init__.py裏用於獲取__all__ def packet(name): if not name in _packet_: _packet_[name] = [] return _packet_[name]
# 目錄結構 #|--common.py(就是上面的裝飾器文件) #|--demo.py #|--package_a # |--__init__.py # |--class_a.py 類ClassA # |--class_b.py 類ClassB
首先在模塊中處理咱們建立的類code
# ./package_a/class_a.py import common # 使用export裝飾器,裝飾要導出的類或函數 @common.export class ClassB(object): def __init__(self): print 'This is ClassB.'
而後在包的__init__.py中修改包自身對象
# ./package_a/__init__.py import common # 注意,這步很重要!!!導入將要導出的子模塊,須要具體模塊名字,此處import * 不可用 from . import class_a, class_b # 用packet初始化包的__all__,主要是用於支持 "from . import *" 導入 __all__ = common.packet(__name__) # 由於用__all__會影響"from . import *"。因此用export把__init__.py裏的成員,加入__all__ @common.export def pafunc(): """ 這是一個包內部的函數 """ print('pafunc')
最終就能夠實現咱們前面所指望的導入方式了。it
# ./demo.py from package_a import * a = ClassA()