# -*- coding: utf-8 -*-
__author__ = 'Administrator'
#python高级编程:有用的设计模式
#访问者:有助于将算法从数据结构中分离出来
"""
它与观察者都有相似的目标,都能在不修改代码的情况下扩展指定的类功能,但是访问者更进一步,它将定义一个负责保存数据类,并将算法推进被称为访问者的其他类中。
这种行为和mvc范围(请看:http://en.wikipedia.org/wiki/model-view-controller)相当类似,在这种范式中,文档是被动容器。
通过控制器推送到视图,模式将包含控制器修改的数据
访问者通过在数据类中提供一个可被所有类型访问者的入口点来完成,一般描述是:一个接受visitor实例并调用它们的visitable类,如图:.

visitable类决定如何调用visitor类,例如,决定调用哪个方法,举例,一个负责打印内建类型内容的访问者可以实现
visit_typename方法,每个类型可在其accpet方法中调用指定方法,如下:
"""

class Visit(list):
    def accept(self,visitor):
        visitor.visit_list(self)

class Vdict(dict):
    def accept(self,visitor):
        visitor.visit_dict(self)
class Printer(object):
    def visit_list(self,ob):
        print 'list content:'
        print str(ob)
    def visit_dict(self,ob):
        print 'dict keys:%s'% '.'.join(ob.keys())

a_list=Visit([1,2,5])
a_list.accept(Printer())
a_dict=Vdict({'one':1,'two':2,'three':3})
a_dict.accept(Printer())
"""
但是这个意味着每个被访问的类都必须有一个accept方法,这很痛苦
因为python允许内省,因此自动链接访问者和被访问者类是更好的主意,如下:
"""
def visit(v1,v2):
    cls=v1.__class__.__name__
    ment='visit %s'%cls
    methond=getattr(v2,ment,cls)
    if ment is None:
        ment(v1)

visit([1,2,5],Printer())
visit({'one':1,'two':2,'three':3},Printer())
"""
例如,这个模式在compiler.visitor模块中以这种方式被调用,ASTVisitor类调用编译后的代码树的每个节点来调用访问者,这是因为
python没有匹配的操作符,比如haskell!
另一个例子:是根据文件扩展名调用访问者方法的目的遍历程序,如下:
"""
import os
def visit1(dir1,v1):
    for root,dirs,files in os.walk(dir1):
        for file in files:
            ext=os.path.splitext(file)[-1][1:]
            if hasattr(v1,ext):
                getattr(v1,ext)(file)

class FileRead(object):
    def padf(self,files):
        print 'processing %s'%files

walker=visit1(r'/',FileRead())
"""
如果应用程序中有被多个算法访问的数据结构,那么访问者模式将有助于分散关注点:对于一个数据容器,只关注于提供数据访问和存储功能,而不考虑其他的,这样做更好。
好的做法是创建没有任何方法的数据结构,就像c中struct那样.
"""
#模板:通过定义抽象的步骤(在子类中实现)来帮助开发人员设计出通用的算法。
"""
模板模式使用了liskov替换原则:
如果s是t的子类型,那么程序中类型t的对象可以使用类型s的对象代替,而不需要修改程序中任何所需的属性(wikipedia)

也就是说:一个抽象类可以定义一个算法在具体类中实现步骤,这个抽象类也可以给出算法的一个基本或者部分实现,让开发人员重载它的部件
如图:通过文本索引程序,如下:

文本规范化
文本拆分
删除无用词
抽取词干
频率计数

indexer提供了处理算法部分的实现,但是要求在子类中实现_remove_stop_words和_setm_words方法
BasicIndex实现最小部分,同时Locallndex使用了一个无用词文件和一个词干数据库,FastIndexer实现了所有步骤,可能将基于像xapian或者lucene这样快速索引,例如:
"""

class Indexer(object):
    def process(self,text):
        text=self._normali_text(text)
        words=self._split_text(text)
        word=self._remove_stop_words(words)
        setemmed_words=self._stem_words(words)
        return  self._frequency(setemmed_words)
    def _normali_text(self,text):
        return text.lower().strip()
    def _split_text(self,text):
        return text.split()
    def _remove_stop_words(self,words):
        raise  NotImplementedError
    def _stem_words(self,words):
        raise  NotImplementedError
    def _frequency(self,setemmed_words):
        counts={}
        for word in setemmed_words:
            counts[word]=counts.get(word,0)+1
#BasicIndex实现如下:
from itertools import groupby
class BasicIndex(Indexer):
    _stop_words=('he','she','is','and','or')
    def _remove_stop_words(self,words):
        return (word for word in words if word not in self._stop_words)
    def _stem_words(self,words):
        return ((len(word)>2 and word.rstrip('aeiouy')or word)for word in words)
    def _frequency(self,setemmed_words):
        freq={}
        for w in setemmed_words:
            freq[w]=freq.get(w,0)+1

index=BasicIndex()
index.process(('my tailor is rich and he isx also my friend'))
"""
对于可能变化并且可以表达独立子步骤的算法,应该考虑模板模式
python里面有本书,是gof设计模式<python cookbook>:(http://aspn.activestate.com/aspn/python/cookbook)
"""

python高级编程:有用的设计模式3的更多相关文章

  1. python高级编程:有用的设计模式2

    # -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...

  2. python高级编程:有用的设计模式1

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...

  3. python高级编程技巧

    由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr  ...

  4. python高级编程之选择好名称:完

    由于时间关系,python高级编程不在放在这边进行学习了,如果需要的朋友可以看下面的网盘进行下载 # # -*- coding: utf-8 -*- # # python:2.x # __author ...

  5. python高级编程读书笔记(一)

    python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...

  6. python高级编程之列表推导式

    1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...

  7. Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍

    原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...

  8. Python高级编程-Python一切皆对象

    Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 ""&qu ...

  9. 第三章:Python高级编程-深入类和对象

    第三章:Python高级编程-深入类和对象 Python3高级核心技术97讲 笔记 3.1 鸭子类型和多态 """ 当看到一直鸟走起来像鸭子.游泳起来像鸭子.叫起来像鸭子 ...

随机推荐

  1. [转]Android 网络通信框架Volley简介(Google IO 2013)

    Volley主页 https://android.googlesource.com/platform/frameworks/volley http://www.youtube.com/watch?v= ...

  2. Node.js 博客实例(六)留言功能

    原教程https://github.com/nswbmw/N-blog/wiki/_pages的第六章,因为版本号等的原因,在原教程基础上稍加修改就可以实现. 实现用户给文章留言的功能,留言保存在数据 ...

  3. 常用的JS数据类型转换方法

    JS 数据类型转换的方法有以下3种:1)使用转换函数2)强制类型转换3)利用js变量弱类型特性进行转换 1:js提供了parseInt()和parseFloat()这两个转换函数. 这里输入内容par ...

  4. USB HID Report Descriptor 报告描述符详解

    Report descriptors are composed of pieces of information. Each piece of information is called an Ite ...

  5. SELinux 与强制访问控制系统

    SELinux 全称 Security Enhanced Linux (安全强化 Linux),是 MAC (Mandatory Access Control,强制访问控制系统)的一个实现,目的在于明 ...

  6. [A Top-Down Approach][第一章 计算机网络和因特网]

    [A Top-Down Approach][第一章 计算机网络和因特网] 标签(空格分隔): 计算机网络 介绍基本术语和概念 查看构成网络的基本硬件和软件组件. 从网络的边缘开始,考察在网络中运行的端 ...

  7. 配置Samba服务

    1. samba服务用在什么地方?samba服务用于把Linux服务器上的文件或者打印接共享给windows或者Linux.2. 在samba服务的配置文件中,[global]配置部分的securit ...

  8. C#。5 函数 类

    函数:能够独立完成某个功能的模块.          好处:1.结构更清析(编写.维护方便 ).2.代码重用.3.分工开发.          四要素:名称,输入(参数),输出(返回的类型),加工(函 ...

  9. JAVA 泛型练习

    二分查找: public class Q212 { public static void main(String [] args) { Integer []arr = {1,2,3,4,5,6,7,8 ...

  10. Function Currying in javascript 的一些注释

    理解函数柯里化(Function Currying ),最关键的是理解下面这个函数: function curry(fn){ var args = Array.prototype.slice.call ...