目錄
創(chuàng)新互聯致力于互聯網網站建設與網站營銷,提供網站建設、成都網站設計、網站開發(fā)、seo優(yōu)化、網站排名、互聯網營銷、重慶小程序開發(fā)公司、公眾號商城、等建站開發(fā),創(chuàng)新互聯網站建設策劃專家,為不同類型的客戶提供良好的互聯網應用定制解決方案,幫助客戶在新的全球化互聯網環(huán)境中保持優(yōu)勢。插件化開發(fā)...1
動態(tài)導入:...1
插件化編程技術:...3
__slots__.4
未實現和未實現異常:...6
運算符重載中的反向方法:...6
例:notepad++中插件;firefox、chrome插件;eclipse;
運行時,根據用戶(程序員)需求(如提供字符串),找到模塊的資源動態(tài)加載起來;
1、__import__(),內建函數;
2、importlib.import_module(),import_module(name, package=None),支持絕對導入和相對導入,相對導入則必須要設置package;
import語句本質上就是調用__import__()這個函數,但不建議直接使用__import__(),建議使用importlib.import_module();
1、內建函數__import__();
__import __(name,globals=None,locals=None,fromlist=(),level=0)
name,模塊名;
sys = __import__('sys')?? #等價于import sys,運行時加載
例:
example_module_test1.py
class A:
def show(self):
print(type(self).__name__)
print(type(self.__module__))
example_plugins.py
if __name__ == '__main__':
mod = __import__('example_module_test1')?? #同import example_module_test1
getattr(mod,'A')().show()
輸出:
A
例:
def plugin_load():
mod = __import__('example_module_test1')?? #加載后會放到sys.modules里,搜索順序是在sys.path中找
# print(type(mod))??? #
getattr(mod,'A')().show()?? #getattr(object, name[, default]) -> value,等價于mod.A().show()
# mod.A().show()
if __name__ == '__main__':
plugin_load()
輸出:
A
例:
def plugin_load(plugin_name:str,sep=':'):
m,_,c = plugin_name.partition(sep)
mod = __import__(m)
cls = getattr(mod,c)
return cls()
if __name__ == '__main__':
# plugin_load()
plugin_load('example_module_test1:A').show()
2、importlib.import_module():
例:
import importlib
def plugin_load(plugin_name:str,sep=':'):
# m,_,c = plugin_name.partition(sep)
m,c = plugin_name.split(sep)
mod = importlib.import_module(m)?? #推薦用此種,不要用__import__()
cls = getattr(mod,c)
return cls()
if __name__ == '__main__':
# plugin_load()
plugin_load('example_module_test1:A').show()
輸出:
A
依賴的技術:
reflection,反射,運行時獲取類型的信息,可動態(tài)維護類型數據;
動態(tài)import,推薦使用importlib.import_module(),實現動態(tài)import模塊的能力;
多線程,可開啟一個線程,等待用戶輸入,從而加載指定名稱的模塊;
加載的時機:
程序啟動時?還是程序運行中?
程序啟動時,像pycharm這樣的工具,需要很多組件,這些組件也可能是插件,啟動的時候掃描固定的目錄,加載插件;
程序運行時,程序運行過程中,接受用戶指令或請求,啟動相應的插件;
兩種方式各有利弊,如果插件過多,會導致程序啟動很慢,如果用戶需要時加載,若插件太多或依賴多,插件也會啟動慢;
所以先加載必須的、常用的插件,其它插件使用時,發(fā)現需要,動態(tài)載入;
應用:
軟件的設計不可能盡善盡美,或在某些功能上,不可能做的專業(yè),需要專業(yè)的客戶自己增強;
如notepadd++,它只需要做好一個文本編輯器就可以了,其它增強功能都通過插件的方式提供,如拼寫檢查、HTML預覽、正則插件等;要定義規(guī)范、定義插件從哪里加載、如何加載、必須實現的功能等;
接口和插件區(qū)別:
接口往往是暴露出來的功能,接口指的是操作(方法|函數),如模塊提供了函數和方法,加載模塊后調用這些函數完成功能;接口也是一種規(guī)范,它約定了必須實現的功能(必須提供某名稱的函數),但不關心怎么實現這個功能;api,application program interface;url指向的是后臺應用中某個類的方法;
插件是把模塊加載到系統(tǒng)中,運行它,增強當前系統(tǒng)功能,或提供系統(tǒng)不具備的功能,往往插件技術應用在框架設計中,系統(tǒng)本身設計簡單化、輕量級、實現基本功能后,其它功能通過插件加入進來,方便擴展;
銷售:
插件化需求,旗艦版、家庭版;
另一些軟件把相應功能的菜單隱藏了,通過序列號可打開隱藏的這些功能;
軟件達到一定規(guī)模,必須做成框架,越需要插件化思想;常用的先加載,不常用的懶加載;
都是字典惹的禍,字典為了提升查詢效率,必須用空間換時間(為了hash得占用一定的空間);
一般來說,一個對象,屬性都存儲在字典中便于查詢,問題不大;但如果數百萬個對象,字典就有點大了;這個時候,能否把屬性字典__dict__給省了;py提供了__slots__;
可理解為就給這幾個槽位放東西,用__slots__規(guī)定有什么樣的屬性;
實例用;標準庫中用得多;
限制實例暴露出的屬性供別人使用;
類屬性不影響;
應用場景:
未來可能產生大量實例,這些實例中有不需要的屬性,用__slots__暴露出可用的屬性,且用元組形式列出(是可迭代對象均可,一個屬性時字符串也可);
當要使用數百萬個對象,且內存容量較為緊張的場景;
__slots__ = 'p1'或__slots__ = 'p1','p2'均可,建議用元組形式__slots__ = ('p1','p2'),__slots__告訴解釋器,實例的屬性都叫什么,一般來說既然要節(jié)約內存,最好還是用元組,一旦類提供了__slots__就阻止實例產生__dict__來保存實例的屬性;
繼承類的實例不受__slots__影響,__slots__管不到自己的子類,控制不了子類;__slots__不影響子類實例,不會繼承下去,除非子類里面自己也定義了__slots__;__slots__一般在子類上用,而且是最下面的子類,父類功能不全;
例:
class A:
x = 123
__slots__ = ('p1','p2')?? #__slots__ = 'p1'或__slots__ = 'p1','p2'均可,建議用元組形式__slots__ = ('p1','p2'),__slots__告訴解釋器,實例的屬性都叫什么,一般來說既然要節(jié)約內存,最好還是用元組,一旦類提供了__slots__就阻止實例產生__dict__來保存實例的屬性
def __init__(self):
self.p1 = 1
self.p2 = 2
def showme(self):
print('I am A.{}'.format(self.p1))
print(A.__dict__)
# print(A().__dict__)?? #X,實例屬性被限制,實例的__dict__消失了
print(A().__slots__)
a = A()
a.p2 = 200
# a.x = 300?? # AttributeError: 'A' object attribute 'x' is read-only
A.x = 500
輸出:
{'__module__': '__main__', 'x': 123, '__slots__': ('p1', 'p2'), '__init__':
('p1', 'p2')
1 200
例:
class A:
x = 123
__slots__ = ('p1','p2')
def __init__(self):
self.p1 = 1
self.p2 = 2
def showme(self):
print('I am A.{}'.format(self.p1))
class B(A):
def __init__(self):
self.b1 = 500
print(B().__dict__)?? #繼承類的實例不受__slots__影響,__slots__管不到自己的子類,控制不了子類;__slots__不影響子類實例,不會繼承下去,除非子類里面自己也定義了__slots__;__slots__一般在子類上用,而且是最下面的子類,父類功能不全
輸出:
{'b1': 500}
print(type(NotImplemented))
print(type(NotImplementedError))
輸出:
例:
class A:
def showme(self):
raise NotImplementedError
print(A().showme())
例:
class Add:
def __init__(self,x:int):
self.x = x
def __add__(self, other):
print('__add__',self)
# return self.x + other.x
return self.x + other
# def __add__(self, other):
#???? print('__add__',self)
#???? try:
#???????? res = self.x + other.x
#???? except:
#???????? try:
#???????????? o = int(other)
#???????? except:
#???????????? o = 0
#???????? res = self.x + o
#???? return res
# def __add__(self, other):
#???? print('__add__',self)
#???? try:
#???????? o = int(other.x)
#???? except:
#???????? o = 0
#???? return self.x + 0
def __iadd__(self, other):
print('__iadd__',self)
return self.x + other.x
def __radd__(self, other):
print('__radd__',self)
# return self.x + other.x
return self + other
a = Add(4)
b = Add('abc')
# print(a+b)
# print(a+=b)
# print(b+a)
# print(a+1)?? #不是1(int)沒有實現__add__(),int中有所有的方法
print(1+a)?? #1+a等價于1.__add__(a),而Int類實現了__add__(),不過這個方法對于這種加法的返回值是NotImplemented,解釋器發(fā)現是這個值,就會發(fā)起對第二操作對象的__radd__()調用
輸出:
__radd__ <__main__.Add object at 0x7f42d83acfd0>
__add__ <__main__.Add object at 0x7f42d83acfd0>
5
例:
class Add:
def __init__(self,x:int):
self.x = x
def __add__(self, other):
print('__add__',self)
return self.x + other.x
def __iadd__(self, other):
print('__iadd__',self)
return self.x + other.x
def __radd__(self, other):
print('__radd__',self)
# return self.x + other.x
return self + other
class B:
def __init__(self,x):
self.x = x
a = Add(4)
b = B(6)
print(a+b)
print(b+a)?? #b+a等價于b.__add__(a),但類B沒有實現__add__(),就去找a的__radd__()方法
輸出:
__add__ <__main__.Add object at 0x7f02a03f7160>
10
__radd__ <__main__.Add object at 0x7f02a03f7160>
__add__ <__main__.Add object at 0x7f02a03f7160>
10
另外有需要云服務器可以了解下創(chuàng)新互聯cdcxhl.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。