`
yezongbo
  • 浏览: 30339 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Mix-in技术与分布类编程

阅读更多
1. Mix-in技术与分布类编程
本文利用Mixin技术实现了如何将一个类以分布的形式进行编程。非常适用于不断渐近的开发过程,等产品成熟稳定后,可以考虑合并为一个完整的类。这是一个Mixin技术具体应用的例子。

大家一看到这个题目,看到“分布类编程”可能会认为是一种什么新技术,其实只不过是我个人所创,是指一个类的实现由多个文件(或模块)组成。至于它如何构成,有何作用,及相应的实例且听我慢慢道来。


1.1. Mix-in技术简介
关于Mix-in技术本人有专门的文章讲述,这里就不再赘述,而只进行简单地介绍。

如果我们在运行时改变一个类的基类或类的方法、属性等就叫做Mix-in。那么它与类派生和重载有什么区别呢?根本的区别就是它的动态性。派生和重载是在程序运行前就已经对类进行了修改,它的改变是确切存在于某个文件中的,这种改变在运行时是稳定的。而Mix-in是在运行时才对相应的类发生作用,其运行时的表现与文件中所描述可能有所区别,而且随着运行环境的不同其表现也可以发生变化。另外,对于派生后的类,在运行时创建其一个实例就可以使用了。而使用Mix-in技术,我们需要将新的基类或方法先加入到原来的类中,然后再创建实例进行应用。

Mix-in技术的主要实现方法有两种:加入基类和加入方法。加入基类则相当于从基类进行派生,从而使原来的类具有基类的方法和属性。加入方法使来的类具有新的方法,如果存在加入的方法与原类中的某个方法同名,则新的方法将替换原来的方法(这个规则不是必然的,因为Mix-in的实现是你自已编写的,而不是固定不变的)。加入基类可以修改类的__bases__属性。加入方法可以使用内置函数getattr()和setattr()来实现。那么对于这种Mix-in技术在实现时还要考虑当新的方法与原方法重名的处理。

之所以会有这种伟大的Mix-in技术的存在,完全要得益于Python语言的动态性(当然可能不止一种语言能够实现这种技术),它允许你在运行时修改类所有的属性,也可以增加新的属性。通过setattr()我们就可以向一个类增加新的方法,并且使用它。


1.2. 分布类的构成
类是对象的定义和描述,通过类我们就可以生成实例,即对象,用它进行处理。分布类,即表明类的定义不是一次性定义出来,而是分布在不同的文件或模块(以后我们就叫它们为分布类文件或分布类模块)中定义的。可能的一种类结构的分布如下:


    +----原始类
    +----基类1
    +...
    +----基类n
    +----新功能1
    +...
    +----新功能2
    +----Mix-in模块
上面的意思就是在一个目录下,有一个原始类,可能有n个基类模块,有n个新功能模块。最后为了实现Mix-in技术还需要一个Mix-in模块,而这个模块可以是你自已编写的。更复杂的结构可能是原始类下还有子目录,但处理方法都是一样的。

在进行基类与新功能的编程时要考虑重名方法的情况。在新功能模块中,方法定义应按照类的方法进行定义,即第一个参数应为对象实例参数,如self。

在运行时,应先使用Mix-in模块中的处理函数将基类与新功能加入到原始类中,然后再生成类的实例,进行使用。

大家可以看到,将类分成多个文件进行编程并不复杂,而Mix-in的处理是比较复杂的,应根据实际情况进行处理。


1.3. 分布类的作用
为什么要使用分布类呢?就我个人来说,主要有以下的好处:

清晰。把一个类的不同功能分组放在不同的模块中,可以清晰地看出类的构成,容易理解,维护起来相对容易。我们在写程序时,可以将最核心的功能写在一个文件中,在其中定义类的属性,类的初始化,及一些最基本的功能。然后对于类的扩展,我们可以根据功能分组放到不同的文件中。这样使得每个文件所描述的功能相对集中,而不再是拥肿的代码。
灵活。如果我们的类的功能耦合性非常小,那么增加、卸载功能都是相当的容易,只要把相应的文件加入或去掉就可以了。在调试程序和定位错误时可能会很方便。如果我们想使某些功能有效,就加入相应的文件,反之,去掉相应的文件。如果发现有错误,可以通过一个文件一个文件地减少,从而进行一个文件一个文件地进行排除。
那么可能带来的不便是:文件变多,没有一个完整的静态描述。那么如果喜欢静态类,我们完全可以在类的功能测试完全之后再合并成静态类。至于需不需要这样做完全看你自已了。


1.4. 使用实例
下面举一个本人所写的FlyEdit程序中所用到的例子。FlyEdit是一个编辑器,它的基本结构就是建立在分布类的基础之上,其中还有一些特别的处理。FlyEdit的分布类模块放在两个目录下,一个为modules,另一个在plugin中。modules为相对核心的部分;plugin中为可由用户自行编写的插件功能模块。在FlyEdit中,最主要的一个类是编辑器类(Editor),它实现了编辑器的基本功能,同时规定了分布类模块某些功能的执行位置(如分布类模块的初始化就放在Editor类的初始化函数内,而且放在所有的可视控件初始化完成之后)。这个类放在主程序flyedit.pyw中。同时flyedit.pyw中在生成编辑器类时先进行Mix-in的处理,然后再生成类的实例。


1    import register
2    register.registerpackage(Editor, 'modules')
3    register.registerpackage(Editor, 'plugin')
4    root=Tk()
5
6    from windowlist import windowlist
7    windowlist=windowlist(root)
8    Editor(root, file, windowlist)
9    root.mainloop()
第1行导入register模块。它是我写的实现Mix-in功能的模块。

第2,3行,对modules子目录和plugin子目录下的文件进行Mix-in处理,将新功能加到Editor类上。在分布类模块中不仅有新的方法,还有一些新增的数据,如菜单等。这样为了使分布类的加入顺序不变,将modules和plugin目录做成python包的形式进行处理(即加入__init__.py文件);同时在包的__init__.py文件中定义了__all__列表,用来说明哪些模块应该Mix-in,并且加入的顺序如何。

第8行,使用新的类创建实例。

下面举一个这样的包结构。


+----modules
        +----__init__.py
        +----a.py
        +----b.py
对于__init__.py文件,内容可能为:


__all__=['a', 'b']
在modules目录下共有三个文件,其中__init__.py文件记录了哪些模块将Mix-in到待处理的类中去。它通过定义一个全局变量__all__来实现。__all__为一个列表,每一项记录了要Mix-in到类中去的模块文件名(没有.py的后缀);同时列表的顺序表明每个模块Mix-in的顺序。a.py和b.py即为真正的分布类模块。从__all__的内容上看,先处理a.py再处理b.py。如果想改变处理顺序或去掉哪些模块,则只要修改__all__的列表值即可,而不用将相应的文件删除。

对于分布类模块,如a.py中应定义要Mix-in到类中去的方法或属性。同时也应定义一个__all__列表,其中列出所有要放入到类中去的方法、属性的字符串名称。那么在进行Mix-in处理时,只有在__all__中定义的方法或属性才会被处理。

那么Mix-in过程是如何实现的呢?下面将FlyEdit中所用到的register模块简述一下。


01        #register functions to a class
02        def registerpackage(class_, modulename):
03            module=__import__(modulename)
04            if hasattr(module, '__all__'):
05                for i in module.__all__:
06                    register(class_, modulename+'.'+i)
07
08        def register(class_, modulename):
09            import types
10            module=my_import(modulename)
11            if hasattr(module, 'init'):
12                value=getattr(module, 'init')
13                class_.initlist.append(value)
14            if not hasattr(module, '__all__'): return
15            for name in module.__all__:
16                property=getattr(module, name)
17                t=type(property)
18                if t in (types.DictType, types.TupleType, types.ListType):
19                    if hasattr(class_, name):
20                        value=getattr(class_, name)
21                        if t == types.DictType :
22                            value.update(property)
23                        else:
24                            value=value+property
25                    else:
26                        value=property
27                    setattr(class_, name, value)
28                else:
29                    if hasattr(class_, name):   #exist a func
30                        delattr(class_, name)
31                    setattr(class_, name, property)
32
33        def my_import(name):
34            mod = __import__(name)
35            components = name.split('.')
36            for comp in components[1:]:
37                mod = getattr(mod, comp)
38            return mod
02行,定义函数registerpackage,用于将一个包结构Mix-in到类上。

03行,导入包。由于这里使用字符串名字作为包名,故应使用__import__内置函数。

4行到6行,判断如果包中含有__all__属性(变量),则依次取出__all__的值(每个值为一个模块名),然后把每个模块名与包名相接,生成“包名.模块名”的可调用的形式,再调用register函数Mix-in到类中。

08行,定义将某个模块Mix-in到指定类的函数。

10行,导入真正的模块。使用__import__函数时,对形如“包名.模块名”的模块,只会返回包对象,而不是最后的模块对象。故调用一个可以真正返回模块对象的函数my_import。

11行到13行,判断模块是否有init属性,如果有则取出放到类的初始化列表中(这个处理是针对FlyEdit所特有的,主要是想解决某些模块需初始的问题,在你的应用中可以不使用)。

14行,判断模块如果没有__all__属性,则不会进行Mix-in处理。这样,只有定义在__all__列表中的内容才会被Mix-in,而其它的内容会被看到“私有”内容对待而不会Mix-in。

从15行到31行,是真正的Mix-in的处理。处理的对象是__all__列表中所有的元素。

16行,根据属性的字符串名,取出分布类模块中相应的属性。

17行,得到属性相应的类型。

18行到27行,如果属性类型为字典,元组(tuple),列表时,当类已经存在同名的值时,将新值添加到原值中;当不存在同名的值时,将新值加入到类中即可。

28行到31行,如果属性为其它类型,则先删除原值,再增加新值。

33行到38行,实现将“包名.模块名”形式的模块导入,返回模块对象。此处不详说了。


1.5. 结论
分布类编程在软件开发阶段可以作为一种调试与功能编写的有力方法。同时在软件应用阶段可以作为一种插件技术而使用。大家要注意的是,本文实例中所介绍的具体的分布类的构成与Mix-in方法的实现都是基于FlyEdit的实现。大家在实现自已的项目时应使用自已的方式。
分享到:
评论

相关推荐

    uniapp 电商项目模版--mix-mall.zip

    【标题】"uniapp 电商项目模版--mix-mall.zip" 提供的是一个基于uniapp框架构建的电商项目模板,名为"mix-mall"。这个模板为开发者提供了一个快速搭建电商平台的基础架构,包含了必要的页面、组件和功能,旨在简化...

    Laravel开发-laravel-mix-twig-extension

    `laravel-mix-twig-extension`是这样一个工具,它为Laravel Mix添加了对Twig模板引擎的支持。Laravel Mix是由Jeffrey Way创建的一个强大的前端构建工具,它基于Webpack,用于简化CSS和JavaScript的编译、打包过程。...

    电商项目模版-mix-mall.zip

    2. **后端架构**:电商项目通常需要强大的后端支持,Mix-Mall可能使用了Spring Boot、Django、Node.js等后端技术栈,为API接口提供服务,处理用户请求、数据存储与处理、订单管理等业务逻辑。 3. **数据库设计**:...

    Mix-Copula.zip_Mix-Copula_copula 注释_mix_混合Copula函数估计_辅助学习

    混合Copula(Mix-Copula)是统计学和金融工程领域中的一种重要工具,用于建模不同变量之间的依赖关系,特别是在非线性关联和多态性分布的情况下。它结合了多个Copula函数,以更好地适应数据的复杂结构。Copula理论...

    mix-mall.rar

    本文将深入探讨uni-app在电商项目中的具体实现、特点以及与其他技术如vue和java的协同工作方式。 首先,uni-app是H5、小程序、APP等多端统一的开发框架,由DCloud(即HTML5 Plus)推出。它采用Vue.js语法,支持Vue...

    Mix-and-Match Tuning for Self-Supervised Semantic Segmentation

    In this study, we overcome this limitation by incorporating a "mix-and-match" (M&M) tuning stage in the self-supervision pipeline. The proposed approach is readily pluggable to many self-supervision ...

    凌华MIX-110嵌入式机箱选型样本.pdf

    凌华MIX-110嵌入式机箱还包含了8位GPIO接口,其中包含4个输入和4个输出,这在工业控制中十分有用,可以与各种传感器和执行器配合使用。音频方面,它配备了Realtek ALC892 5.1通道高保真音频解码芯片,支持常见的音频...

    mix-mall 电商项目模版.rar

    《基于uni-app的mix-mall电商项目模版详解》 在现代互联网开发中,电商平台的构建已经成为企业不可或缺的一部分。为了快速高效地搭建电子商务系统,开发者往往会选择使用现成的项目模版作为起点。本文将详细解析名...

    laravel-mix-merge-manifest:该扩展支持多重混音配置,而不会覆盖mix-manifest.json文件

    Laravel Mix-合并清单该扩展支持多重混音配置,而不会覆盖mix-manifest.json文件。 它将新清单合并到现有清单中。用法首先,安装扩展程序。 // Laravel Mix v5npm install laravel-mix-merge-manifest@v1 --save-dev...

    laravel-mix-svg-sprite:用于Laravel Mix的SVG Sprite组件

    laravel-mix-svg-sprite 用于Laravel Mix的SVG精灵组件,包装了和。 安装 使用npm安装: $ npm install --save-dev laravel-mix-svg-sprite 用法 该组件向Mix添加了一个额外的API,以创建单独的SVG文件的SVG子画面...

    Laravel开发-kirby-laravel-mix-helper

    "Laravel开发-kirby-laravel-mix-helper"项目就是针对这个主题的一个辅助工具,它帮助开发者更高效地理解和使用Laravel Mix的不同版本特性。 首先,Laravel Mix是由Jeffrey Way创建的,它是基于Webpack的,用于处理...

    Laravel开发-mix-auth

    在这个项目中,"mix-auth"可能是指将Laravel的后端身份验证功能与Laravel Mix的前端构建能力相结合,创建一个完整的前后端认证系统。 **Laravel Mix** Laravel Mix是由Jeffrey Way创建的,它是Laravel生态的一部分...

    mix-starter_a-star_

    【标题】"mix-starter_a-star_" 暗示我们正在讨论的是一个名为 "mix-starter" 的项目,它与 "a-star" 相关。"A-Star" 是一种路径搜索算法,在游戏开发、机器人导航等领域广泛应用。"mix-starter" 可能是这个项目的...

    车联网中Mix-zone的隐私保护机制研究.pdf

    Mix-zone技术是目前研究最为广泛的一种位置隐私保护方案。其核心思想是,在车辆通过某些特定区域(Mix-zone)时,车辆更换其在网络中使用的假名(Pseudonyms),并且这些假名是在指定的地理区域内频繁更换的。假名是...

    Laravel开发-mix-function

    `mix-function-master`这个压缩包可能包含了一个示例项目,展示了如何配置和使用`mix`。解压后,你可以查看`webpack.mix.js`文件,了解具体的配置细节。此外,运行`npm run dev`或`npm run production`(根据环境...

    laravel-mix-vue3:适用于Vue 3,Typescript和JSX的Laravel Mix扩展

    npm install laravel-mix-vue3 --save-dev//oryarn add laravel-mix-vue3 -D 如果Laravel Mix无法安装以下内容,请确保安装以下内容 npm install @types/webpack-env @vue/compiler-sfc vue-loader@next laravel-...

    laravel-mix-vue-css-modules:Laravel Mix Vue CSS模块

    安装npm i laravel-mix-vue-css-modules --save-dev推荐的v3Laravel混合Laravel Mix Vue CSS模块预处理器安装命令v5 v2 SCSS npm install laravel-mix-vue-css-modules@2 v5 SCSS,LESS,STYLUS npm install laravel...

Global site tag (gtag.js) - Google Analytics