# -*- 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. 关闭钩子(shutdown hook)的作用

    DK1.3介绍了java.lang.Runtime class的addShutdownHook()方法.如果你需要在你的程序关闭前采取什么措施,那么关闭钩子(shutdown hook)是很有用的. ...

  2. Mybatis高级映射、动态SQL及获得自增主键

    一.动态SQL 相信大家在用mybatis操作数据库时时都会碰到一个问题,假如现在我们有一个关于作者的list authorList,需要根据authorList里已有的作者信息在数据库中查询相应作者 ...

  3. MySQL 加密/压缩函数

    这些问题可能导致数据值的改变.一般而言,上述问题可能在你使用非二进制串数据类型(如char,varchar,text等数据类型)的情况下发生. AES_ENCRYPT()和AES_DECRYPT() ...

  4. DefaultResouceLoader的设计

    它是什么 DefaultResourceLoader是Spring中的ResourceLoader的默认实现类,也是AbstractApplicationContext的父类,它也可以单独使用,用来从 ...

  5. DELL RACADM 工具使用介绍

    如果iDRAC的IP或者设置出现问题,不能够链接,那么可以通过RACADM这个程序在系统层面可以对iDRAC进行设置,使用的方法以及命令都在下边. RACADM provides command li ...

  6. python模块基础之getpass模块

    getpass模块提供了可移植的密码输入,一共包括下面两个函数: 1. getpass.getpass() 2. getpass.getuser() getpass.getpass([prompt[, ...

  7. AsyncHttpClient 登录 Application Fragment 回调 监听 软键盘

    Activity /**登录界面及登陆后用户首页界面,使用两个Fragment实现*/ public class LoginActivity extends Activity implements L ...

  8. Universal-Image-Loader 示例 工具

    Base public class MyApplication extends Application {     @Override     public void onCreate() {     ...

  9. Tree( 树) 组件[4]

    本节课重点了解 EasyUI 中 Tree(树)组件的使用方法, 这个组件依赖于 Draggable(拖动)和 Droppable(放置)组件.一.方法列表 //部分方法onClick : funct ...

  10. eclipse 插件 最新 eclipse4.x 插件

    Properties  Editor:  中文显示属性配置文件 help ——> install new  SoftWare ——>add Name: xx Location: http: ...