python高级编程:有用的设计模式3
# -*- 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的更多相关文章
- python高级编程:有用的设计模式2
# -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...
- python高级编程:有用的设计模式1
# -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...
- python高级编程技巧
由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr ...
- python高级编程之选择好名称:完
由于时间关系,python高级编程不在放在这边进行学习了,如果需要的朋友可以看下面的网盘进行下载 # # -*- coding: utf-8 -*- # # python:2.x # __author ...
- python高级编程读书笔记(一)
python高级编程读书笔记(一) python 高级编程读书笔记,记录一下基础和高级用法 python2和python3兼容处理 使用sys模块使程序python2和python3兼容 import ...
- python高级编程之列表推导式
1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
- Python高级编程-Python一切皆对象
Python高级编程-Python一切皆对象 Python3高级核心技术97讲 笔记 1. Python一切皆对象 1.1 函数和类也是对象,属于Python的一等公民 ""&qu ...
- 第三章:Python高级编程-深入类和对象
第三章:Python高级编程-深入类和对象 Python3高级核心技术97讲 笔记 3.1 鸭子类型和多态 """ 当看到一直鸟走起来像鸭子.游泳起来像鸭子.叫起来像鸭子 ...
随机推荐
- Tips:javascript 图片放大和取得尺寸
1)获取图片尺寸 <img src="http://img.my.csdn.net/uploads/201309/03/1378223257_7957.jpg" alt=&q ...
- 初学Pexpect
概述 Pexpect 是 Don Libes 的 Expect 语言的一个 Python 实现,是一个用来启动子程序,并使用正则表达式对程序输出做出特定响应,以此实现与其自动交互的 Python 模块 ...
- LDAP索引及缓存优化
一.设置索引 索引将查找信息和 Directory Server 条目关联起来. Directory Server支持以下几种索引: 1出现索引 (pres) - 列出了具有特定属性的条目,与属性的值 ...
- js精度丢失解决办法
/** * 加法运算,避免数据相加小数点后产生多位数和计算精度损失. * * @param num1加数1 | num2加数2 */ function numAdd(num1, num2) { var ...
- Java 坦克小游戏心得
原本是闲得慌无聊才去尝试做这个项目的,因为小时候玩小霸王的游戏机,那个时候经常玩这个游戏吧,特别是喜欢那种自定义地图的模式,觉得自由度非常不错.总之关于这个游戏,想说的一大堆.鉴于能有个空闲的时间,打 ...
- WINDOWS系统下环境变量PATH和CLASSPATH的意思
1 PATH 对于没有包含路径的命令,WINDOWS系统会默认去Windows 目录(C:\windows)和系统目录(C:\windows\system32)查找,如果没有找到,就去PATH变量内包 ...
- RAC RMAN备份
这篇主要介绍的是RAC 环境下的RMAN 备份. 关于Oracle 备份与恢复的一些理论知识参考我的Blog: Oracle 备份 与 恢复 概述 http://blog.csdn.net ...
- 64位Windows 7平台安装32位Timesten,配置ODBC数据源
问题: 由于系统版本原因,客户机只能安装32位的Timesten,但客户机的平台是64位的win 7,安装完成后按照常规的控制面板->管理工具->数据源(ODBC)打开的ODBC数据源管理 ...
- 【转】【C/C++】内存分配函数:malloc,calloc,realloc,_alloca
转自:http://www.cnblogs.com/particle/archive/2012/09/01/2667034.html#commentform malloc: 原型:extern voi ...
- boost
参考博客 http://www.cnblogs.com/lidabo/p/3805487.html http://www.cppblog.com/Robertxiao/archive/2013/01/ ...