[python]在场景中理解装饰器
原来我也自己通过查资料,来学习python的装饰器,但是效果不好。因为没有接触过需要用到装饰器的场景,所以
一起的资料都只停留在纸面上,但是今天偶然看到了vimer的这篇文章:http://www.vimer.cn/2011/04/python%E8%A3%85%E9%A5%B0%E5%99%A8%E7%9A%84%E4%B8%80%E4%B8%AA%E5%A6%99%E7%94%A8.html
我们就根据这篇文章的思路来,在场景中理解python装饰器
其中的一个场景是:爬取数据的时候,目标网站,不稳定。爬虫在爬取数据的时候可能异常。
解决方案:
思路:把爬中的每个方法爬取的数据,都存在硬盘中,存储规则如下:
file_path:/method_name/
file_name:MD5_number.txt
解释:MD5_number是通过方法名和传入的参数计算出来的唯一标识符(搜索一下MD5)这样做的好 处,不需要把数据爬下来之后才能判断是否爬过。
最后:如果方法爬取目标url的数据时异常,暂不执行该方法。最后多跑几次这个爬虫脚本就可以了!
该爬虫调用三个方法,设计一个通用的方法:根据每个方法的方法名和传入的参数通过MD5计算出唯一的标识符(MD5_numbe)。然后在file_path目录中查找文件名为MD5_numbe的文件,如果file_path中的没有这个文件,则按照存储规则存储数据。如果找到了,不存储到硬盘中,直接返回data,用于下一个方法。
————————————
场景结束
++++++++++++
在上面描述的这个场景中,修饰器用在什么地方?
对了!就是那个通用方法,就需要用修饰器来实现,为什么?一步步的来
python中一切东西都是对象。方法就可以做当作对象来传递!
1.什么是方法?
传入参数,然后对传入的参数进行一系列操作。
2.什么是高级方法
方法接受的参数是方法,仅此而已。
3.什么是闭包
当方法1里面有一个方法2,方法2调用的是方法1接收到的参数,最后结果返回方法2。提供这种实现的技术叫做闭包。
说到底修饰器就是一个方法,而传入的参数是方法,并在修饰器中对传入的方法进行一系列的操作(这里用到闭包)。从而实现了,在不修改原方法基础上,增加新的操作。比如上一个场景中的,检验有没有重复爬取数据。
爬中脚本中的代码片段
func_top是上层页面的处理函数,func_sub是子页面的处理函数,func_bottom是最深层页面的处理函数,func_top会在取到子页面url后遍历调用func_sub,func_sub也是同样。
def func_top(url):
data_dict= {} #在页面上获取到子url
sub_urls = xxxx data_list = []
for it in sub_urls:
data_list.append(func_sub(it)) data_dict['data'] = data_list return data_dict def func_sub(url):
data_dict= {} #在页面上获取到子url
bottom_urls = xxxx data_list = []
for it in bottom_urls:
data_list.append(func_bottom(it)) data_dict['data'] = data_list return data_dict def func_bottom(url):
#获取数据
data = xxxx
return data
所以实现方案也就有了:
定义一个装饰器,如果之前取到数据,就直接取cache(file_path)的数据;如果之前没有取到,那么就从网站拉取,并且存入cache中.
import os
import hashlib def deco_args_recent_cache(category='dumps'):
'''
装饰器,返回最新cache的数据
'''
def deco_recent_cache(func):
def func_wrapper(*args, **kargs):
sig = _mk_cache_sig(*args, **kargs)
data = _get_recent_cache(category, func.__name__, sig)
if data is not None:
return data data = func(*args, **kargs)
if data is not None:
_set_recent_cache(category, func.__name__, sig, data)
return data return func_wrapper return deco_recent_cache def _mk_cache_sig(*args, **kargs):
'''
通过传入参数,生成唯一标识
'''
src_data = repr(args) + repr(kargs)
m = hashlib.md5(src_data)
sig = m.hexdigest()
return sig def _get_recent_cache(category, func_name, sig):
full_file_path = '%s/%s/%s' % (category, func_name, sig)
if os.path.isfile(full_file_path):
return eval(file(full_file_path,'r').read())
else:
return None def _set_recent_cache(category, func_name, sig, data):
full_dir_path = '%s/%s' % (category, func_name)
if not os.path.isdir(full_dir_path):
os.makedirs(full_dir_path) full_file_path = '%s/%s/%s' % (category, func_name, sig)
f = file(full_file_path, 'w+')
f.write(repr(data))
f.close()
最后,我们只需要在每个func_top,func_sub,func_bottom都加上deco_args_recent_cache这个装饰器即可~~
参考资料:
浅显理解闭包:https://serholiu.com/python-closures
修饰器:http://jnotes.googlecode.com/svn/trunk/Notes/NotesOnPythonLearning/Python_decorator.html
[python]在场景中理解装饰器的更多相关文章
- Python 标准库中的装饰器
题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...
- 理解Python中的装饰器
文章先由stackoverflow上面的一个问题引起吧,如果使用如下的代码: @makebold @makeitalic def say(): return "Hello" 打印出 ...
- 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档
转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...
- Python(三)对装饰器的理解
装饰器是 Python 的一个重要部分,也是比较难理解和使用好的部分.下面对装饰器做一下简单整理 1. 前言 装饰器实际上是应用了设计模式里,装饰器模式的思想: 在不概念原有结构的情况下,添加新的功能 ...
- 简单说明Python中的装饰器的用法
简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下 装饰器对与 ...
- 浅显易懂的谈一谈python中的装饰器!!
hello大家好~~我是稀里糊涂林老冷,一天天稀里糊涂的. 前一段时间学习了装饰器,觉着这东西好高大上哇靠!!哈哈,一定要总结一下,方便以后自己查阅,也希望帮助其他伙伴们共同进步! 装饰器: 大家可以 ...
- Python类中的装饰器在当前类中的声明与调用
[本文出自天外归云的博客园] 我的Python环境:3.7 在Python类里声明一个装饰器,并在这个类里调用这个装饰器.代码如下: class Test(): xx = False def __in ...
- 【Python】python中的装饰器——@
对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...
- Python 中实现装饰器时使用 @functools.wraps 的理由
Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过 ...
随机推荐
- 取消 virtualStore 注册表[启用和禁止 UAC虚拟化]
近日发现,在win2008R2 x64下运行的服务器程序,其注册表读取路径为: [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SZDomain\itvc1] 但是经 ...
- 取代奶瓶Minidwep-gtk破解WPA 全攻略
取代奶瓶Minidwep-gtk 破 WPA 全攻略 目录 1. CDlinux 下使用 minidwepgtk 获取握手包并使用自带的字典破解 2. 自带的字典破解不出密码时使用 U 盘外挂字典继 ...
- RMAN duplciate 准备时,需要检查的target数据库参数内容
SQL> show parameter audit_file_dest; NAME TYPE VALUE------ ...
- C#控制其它程序
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] ...
- SQL获取本周销售总数
select sum("NUMBER") as WEEK_NUMBER, COMPANY_CODE, PROJECT_CODE from D_VISIT WHERE "D ...
- spring(3) JDBC
Step Description 1 Create a project with a name SpringExample and create a package com.tutorialspoin ...
- IOS开发之不同版本适配问题2(#ifdef __IPHONE_7_0)
继续说说ios不同版本之间的适配 先说一个东西:在xcode当中有一个东西叫targets,苹果的官方文档是这样说的: A target specifies a product to build an ...
- 第50讲:Scala中Variance变化点
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 使用cocos2d-x v3.1开发小游戏(基本框架)
小游戏的组成 欢迎界面 在游戏资源未全部加载完之前就需要载入,避免进入游戏会有一段黑屏时间. 可以用来展示游戏名称或者开发者logo. 开始菜单界面 一般用于显示游戏名称和关卡选择(或者称游戏难度选择 ...
- algo_预备
章 C + +程序设计 大家好!现在我们将要开始一个穿越" 数据结构.算法和程序" 这个抽象世界的特殊旅程,以解决现实生活中的许多难题.在程序开发过程中通常需要做到如下两点:一是高 ...