36插件化开发_slots_radd-创新互联

目录

创新互联致力于互联网网站建设与网站营销,提供网站建设、成都网站设计、网站开发、seo优化、网站排名、互联网营销、重庆小程序开发公司、公众号商城、等建站开发,创新互联网站建设策划专家,为不同类型的客户提供良好的互联网应用定制解决方案,帮助客户在新的全球化互联网环境中保持优势。

插件化开发...1

动态导入:...1

插件化编程技术:...3

__slots__.4

未实现和未实现异常:...6

运算符重载中的反向方法:...6

插件化开发

例:notepad++中插件;firefox、chrome插件;eclipse;

动态导入:

运行时,根据用户(程序员)需求(如提供字符串),找到模块的资源动态加载起来;

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,反射,运行时获取类型的信息,可动态维护类型数据;

动态import,推荐使用importlib.import_module(),实现动态import模块的能力;

多线程,可开启一个线程,等待用户输入,从而加载指定名称的模块;

加载的时机:

程序启动时?还是程序运行中?

程序启动时,像pycharm这样的工具,需要很多组件,这些组件也可能是插件,启动的时候扫描固定的目录,加载插件;

程序运行时,程序运行过程中,接受用户指令或请求,启动相应的插件;

两种方式各有利弊,如果插件过多,会导致程序启动很慢,如果用户需要时加载,若插件太多或依赖多,插件也会启动慢;

所以先加载必须的、常用的插件,其它插件使用时,发现需要,动态载入;

应用:

软件的设计不可能尽善尽美,或在某些功能上,不可能做的专业,需要专业的客户自己增强;

如notepadd++,它只需要做好一个文本编辑器就可以了,其它增强功能都通过插件的方式提供,如拼写检查、HTML预览、正则插件等;要定义规范、定义插件从哪里加载、如何加载、必须实现的功能等;

接口和插件区别:

接口往往是暴露出来的功能,接口指的是操作(方法|函数),如模块提供了函数和方法,加载模块后调用这些函数完成功能;接口也是一种规范,它约定了必须实现的功能(必须提供某名称的函数),但不关心怎么实现这个功能;api,application program interface;url指向的是后台应用中某个类的方法;

插件是把模块加载到系统中,运行它,增强当前系统功能,或提供系统不具备的功能,往往插件技术应用在框架设计中,系统本身设计简单化、轻量级、实现基本功能后,其它功能通过插件加入进来,方便扩展;

销售:

插件化需求,旗舰版、家庭版;

另一些软件把相应功能的菜单隐藏了,通过序列号可打开隐藏的这些功能;

软件达到一定规模,必须做成框架,越需要插件化思想;常用的先加载,不常用的懒加载;

__slots__

都是字典惹的祸,字典为了提升查询效率,必须用空间换时间(为了hash得占用一定的空间);

一般来说,一个对象,属性都存储在字典中便于查询,问题不大;但如果数百万个对象,字典就有点大了;这个时候,能否把属性字典__dict__给省了;py提供了__slots__;

可理解为就给这几个槽位放东西,用__slots__规定有什么样的属性;

实例用;标准库中用得多;

限制实例暴露出的属性供别人使用;

类属性不影响;

应用场景:

未来可能产生大量实例,这些实例中有不需要的属性,用__slots__暴露出可用的属性,且用元组形式列出(是可迭代对象均可,一个属性时字符串也可);

当要使用数百万个对象,且内存容量较为紧张的场景;

__slots__ = 'p1'或__slots__ = 'p1','p2'均可,建议用元组形式__slots__ = ('p1','p2'),__slots__告诉解释器,实例的属性都叫什么,一般来说既然要节约内存,最好还是用元组,一旦类提供了__slots__就阻止实例产生__dict__来保存实例的属性;

继承类的实例不受__slots__影响,__slots__管不到自己的子类,控制不了子类;__slots__不影响子类实例,不会继承下去,除非子类里面自己也定义了__slots__;__slots__一般在子类上用,而且是最下面的子类,父类功能不全;

例:

class A:

x = 123

__slots__ = ('p1','p2')   #__slots__ = 'p1'或__slots__ = 'p1','p2'均可,建议用元组形式__slots__ = ('p1','p2'),__slots__告诉解释器,实例的属性都叫什么,一般来说既然要节约内存,最好还是用元组,一旦类提供了__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__': , 'showme': , 'p1': , 'p2': , '__doc__': None}

('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))

输出:

   #是个值,单值,是NotImplementedType类的实例

   #是类型,是异常,返回type,父类RuntimeError-->父类Exception

例:

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,解释器发现是这个值,就会发起对第二操作对象的__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

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:36插件化开发_slots_radd-创新互联
本文链接:http://myzitong.com/article/isici.html