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 鸭子类型和多态 """ 当看到一直鸟走起来像鸭子.游泳起来像鸭子.叫起来像鸭子 ...
随机推荐
- Synopsys逻辑工艺库
Synopsys逻辑工艺库(DC综合) 逻辑库包括仅与综合过程有关的信息且通过DC用于设计的综合和优化. 这一信息包括引脚到引脚的时序.面积.引脚类型和功耗以及其他DC需要的必须数据. 逻辑库是一个文 ...
- C#利用ODP.NET往oracle中高效插入百万数据
由于工作的原因,要使用winform来处理大量的数据,但是c#自带的System.data.OracleClient效率不是很高,在网上找了很久,找到了ODP.NET,是oracle为c#提供的.貌似 ...
- 移动端(IOS)iframe监听不到 onscroll 事件
问题描述: 我在一个页面A中有瀑布流,点击瀑布流中的图片需要进入到另外一个页面B,点击返回需要回到页面A中点击的位置,为了实现该效果所以在页面A中嵌入iframe,iframe指向页面B,页面B中同样 ...
- 关于.net根目录路径的问题
今天做了一个项目,用了url重写,但是在本地目录是localhost/BK/index.aspx,而其他目录也必须带bk,不带的话就找不到页面,(iis里正常) 应该主目录去掉bk,设置方法,右击网站 ...
- 在MVC中利用uploadify插件实现上传文件的功能
趁着近段的空闲时间,开发任务不是很重,就一直想把以前在仓促时间里所写的多文件上传功能改一下,在网上找了很多例子,觉得uploadify还可以,就想用它来试试.实现自己想要的功能.根据官网的开发文档,同 ...
- 带权并查集 poj1182
首先要注意核心代码 int find(int i){ if(i == fa[i]) return fa[i]; int tt = find(fa[i]); num[i] ...
- 第1章 网络编程基础(4)——TCP/IP通信
TCP协议利用网络层IP协议提供不可靠的通信服务,解决分组的重传和排序问题,为应用程序提供可靠的.端到端的.面向连接的基于字节流的服务. 对等TCP传输实体间的通信具有如下特征: 全双工 只支持两个端 ...
- Sicily 2005.Lovely Number
题目地址:2005.Lovely Number 思路: 若测试数据出现的次数为奇数,则输出它. 所以,可以先排序,若前后相等,前后都设为0,最后不为0的则可以输出. 具体代码如下: #include ...
- javascript学习教程之---如何从一个tab切换到banner幻灯片的转换2
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 腾讯CMEM的PHP扩展(转载)
题外话最近公司在做相关的业务,由于Memcached协议缺少返回码,为了保证业务数据的安全性,不得已只好自己写个扩展来实现需求. 基于memcache扩展的2.2.6的稳定版开发而来.代码已经开源,有 ...