Python-04-基础
一、装饰器(decorator)
- 装饰器本质上也是函数,目的是为其他函数添加附加功能(装饰其他函数)
- Python通过使用装饰器来达到代码的开放与封闭。
原则:
- 不能修改被装饰函数的源代码。
- 不能修改被装饰函数的调用方式。
我们现在有个需求:写一个计时器来统计每个函数执行的时间长度,满足上面的2个原则。
- 实现一:
import time
def timer(func):
start_time = time.time()
func()
stop_time = time.time()
print("The function run time is %s" % (stop_time-start_time))
return func
def f1():
print("This is function F1")
time.sleep(1)
timer(f1)
上述方法虽然可以实现需求,但是它却改变了原函数f1的调用方式,所以不满足第2个原则。
- 我们下面使用装饰器来实现:
import time
def timer(func):
def deco():
start_time = time.time()
func()
stop_time = time.time()
print("The func run time is %s" % (stop_time-start_time))
return deco
@timer
def f1():
print("This is function F1")
time.sleep(1)
f1()
装饰器使用“@+函数名”的语法,当代码运行到@timer的时候,会把下面被装饰的函数f1做为自己的参数,相当于:func = f1,当f1()执行时,实际上执行的是deco()。
- 当被装饰的函数有参数时我们怎么实现呢?
- 参数固定时:
def login(func):
def deco(user):
print("[装饰器]正在验证登录:")
func(user)
return deco
@login
def wel(user):
print("Welcome %s to login the page!" % user)
wel("huyd")
2.参数不固定时:
def login(func):
def deco(*args,**kwargs):
print("[装饰器]正在验证登录:")
func(*args,**kwargs)
return deco
@login
def wel(*args,**kwargs):
print("Welcome {} to login the page!".format(*args,**kwargs))
wel("huyd")
- 当被装饰的函数有返回值时,又该怎么实现呢?
def login(func):
def deco(*args,**kwargs):
print("[装饰器]正在验证登录:")
res = func(*args,**kwargs)
return res # 此处应该将被装饰函数的返回值return
return deco
@login
def wel(*args,**kwargs):
print("Welcome {} to login the page!".format(*args,**kwargs))
return "sucessful" # 被装饰的函数有返回值
wel = wel("huyd")
print(wel)
- 装饰器也可以有自己的参数
def deco_fun1():
print("装饰器功能1")
def deco_fun2():
print("装饰器功能2")
def deco(deco_fun): # 第1层传入装饰器参数(这里只传入了1个参数,也可传入多个)
def outer(main_fun): # 第2层传入被装饰的函数名
def inner(): # 第3层传入被装饰函数的参数
deco_fun()
main_fun()
return inner
return outer
@deco(deco_fun1) # 这样就使用了装饰器deco功能1
def index():
print("我是主程序")
index()
需求:使用装饰器写一个简单的用户认证功能,当登录index页面时使用本地验证用户名,登录home页面时使用LDAP验证。
user,passwd = 'huyd','123'
def auth(auth_type): # 判断装饰器的参数
def outer_wrapper(func):
def wrapper(*args,**kwargs):
if auth_type == "local":
username = input("Username:").strip()
password = input("Password:").strip()
if username == user and password == passwd:
print("\033[32;1mLogin successful!\033[0m")
res = func(*args,**kwargs)
return res
else:
print("\033[31;1mInvalid username or password!\033[0m")
elif auth_type == "ldap":
print("Home page must be LDAP type Login!")
return wrapper
return outer_wrapper
@auth(auth_type="local")
def index():
print("Welcome to index page!")
return "Index"
@auth(auth_type="ldap")
def home():
print("Welcome to home page!")
return "Home"
# index() # 进入index页面时使用本地验证登录
home() # 进入home页面时使用LDAP验证登录
二、生成器(generator)& 迭代器(iterator)
- 迭代器是访问集合中元素的一种方式,迭代器 object从集合中的第一个元素开始访问,知道所有的元素被访问完成.
- 所以迭代器的特点是:只能往前,不能后退
- 迭代器的优点:不需要提前准备整个迭代器中的所有元素,仅仅迭代到某个元素时才计算该元素,而之前或者之后,元素可以不存在或者销毁.因为这个特点,迭代器特别适合遍历文件比较大或者无限的集合.
- 总结下迭代器 iter()的特点吧:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
迭代器是用__next__()来取值的,来看个例子吧:
gen = iter([1,2,3])
# 取值方法一:
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
print(gen.__next__()) #再取值就会报错
# 取值方法二:
for i in gen:
print(i)
能被for直接循环的都是可迭代对象,如列表,字典等。判断一个对象是不是可迭代对象,可以使用isinstance(*, Iterable)来判断。
生成器在被调用的时候返回一个迭代器。生成器有个标志性的语法yield。
当生成器被调用时,yield返回一个值,并记住当前位置,下一次调用时,从yield下一句语句运行返回下一个值。
def catch_mony(amount):
while amount > 0:
amount -= 100
print("又来取钱了!")
yield "给你100吧,剩余:{}".format(amount)
atm = catch_mony(500)
print(type(atm))
print(atm.__next__())
print(atm.__next__())
print("去看电影!。。。")
print(atm.__next__())
======================================
运行结果:
<class 'generator'>
又来取钱了!
给你100吧,剩余:400
又来取钱了!
给你100吧,剩余:300
去看电影!。。。
又来取钱了!
给你100吧,剩余:200
此外,yield还有实现在单线程模式下实现并发运算的效果。如下例:
import time
def consumer(name):
print("{}准备吃包子啦!".format(name))
while True:
baozi = yield # yield也可以用于接收值
print("第{}次的包子来了,被{}吃掉了!".format(baozi, name))
def producer(name):
c1 = consumer('A')
c2 = consumer('B')
c1.__next__()
c2.__next__()
print("{}准备开始做包子了!".format(name))
for i in range(1, 11):
time.sleep(1)
print("{}第{}次做了两个包子。".format(name, i))
c1.send(i) # 将i的值传给yield
c2.send(i) # 将i的值传给yield
producer("老板")
三、Json & pickle 数据序列化
用于序列化的两个模块:
- json,用于字符串 和 python数据类型间进行转换
- pickle,用于python特有的类型 和 python的数据类型间进行转换
- Json模块提供了四个功能:dumps、dump、loads、load
- pickle模块提供了四个功能:dumps、dump、loads、load
import json
data = {'k1':123,'k2':'Hello'}
# json.dumps 将数据通过特殊的形式转换为所有程序语言都认识的字符串
j_str = json.dumps(data)
print(type(j_str),j_str)
# json.loads 将字典形式的字符串转换为字典格式
j_dict = json.loads(j_str)
print(type(j_dict),j_dict)
# json.dump 将数据通过特殊的形式转换为所有程序都认识的字符串,并写入文件
with open('result.json','w') as f:
json.dump(data,f)
#######################################################################
import pickle
# pickle.dumps 将数据通过特殊的形式转换为只有python语言认识的字符串
p_str = pickle.dumps(data)
print(type(p_str),p_str)
# pickle.dump 将数据通过特殊的形式转换为只有Python语言认识的字符串,并写入文件
with open('result.pk','w') as f:
pickle.dump(data,f)
Python-04-基础的更多相关文章
- Python编程语言基础
今天给大家讲解python语言基础~~ 01.python核心数据类型 整型数 int:整数是不带有小数部分的数字 浮点型数 float:浮点数是带有小数部分的数字(小数部分可以是0) 复数 co ...
- Python语言基础与应用 (P16)上机练习:基本数据类型
本文是笔者在学习MOOC课程<Python语言基础与应用> (北京大学-陈斌)中根据上机课时的要求写下在代码 课程总链接: 中国大学MOOC B站 本节课链接 数值基本运算: 33和7+, ...
- Python实验报告——第2章 Python语言基础
实验报告 [实验目的] 1.熟悉在线编程平台. 2.掌握基本的 python 程序编写.编译与运行程序的方法. [实验条件] 1.PC机或者远程编程环境 [实验内容] 1.完成第二章实例01-07,实 ...
- Python文件基础
===========Python文件基础========= 写,先写在了IO buffer了,所以要及时保存 关闭.关闭会自动保存. file.close() 读取全部文件内容用read,读取一行用 ...
- 3.Python编程语言基础技术框架
3.Python编程语言基础技术框架 3.1查看数据项数据类型 type(name) 3.2查看数据项数据id id(name) 3.3对象引用 备注Python将所有数据存为内存对象 Python中 ...
- Python爬虫基础
前言 Python非常适合用来开发网页爬虫,理由如下: 1.抓取网页本身的接口 相比与其他静态编程语言,如java,c#,c++,python抓取网页文档的接口更简洁:相比其他动态脚本语言,如perl ...
- 小白必看Python视频基础教程
Python的排名从去年开始就借助人工智能持续上升,现在它已经成为了第一名.Python的火热,也带动了工程师们的就业热.可能你也想通过学习加入这个炙手可热的行业,可以看看Python视频基础教程,小 ...
- Python爬虫基础之requests
一.随时随地爬取一个网页下来 怎么爬取网页?对网站开发了解的都知道,浏览器访问Url向服务器发送请求,服务器响应浏览器请求并返回一堆HTML信息,其中包括html标签,css样式,js脚本等.我们之前 ...
- 零基础学Python--------第2章 Python语言基础
第2章 Python语言基础 2.1 Python语法特点 2.11注释 在Python中,通常包括3种类型的注释,分别是单行注释.多行注释和中文编码声明注释. 1.单行注释 在Python中,使用 ...
- Python学习基础笔记(全)
换博客了,还是csdn好一些. Python学习基础笔记 1.Python学习-linux下Python3的安装 2.Python学习-数据类型.运算符.条件语句 3.Python学习-循环语句 4. ...
随机推荐
- ABP 初探 之 AbpSession 扩展
Abp的权限管理是基于 Identity,所有的扩展也是基于 claims .claims 有许多默认属性,具体连接 关于 Identity的详细介绍,可以参考园友博客 继承 Microsoft.As ...
- PowerDesigner 15设置mysql主键自动增长及基数
PowerDesigner 15设置mysql主键自动增长及基数 1.双击标示图,打开table properties->columns, 如图点击图标Customize Columns an ...
- [翻译]用 Puppet 搭建易管理的服务器基础架构(1)
我通过伯乐在线翻译了一个Puppet简明教程,一共分为四部分,这是第一部分. 原文地址:http://blog.jobbole.com/87679/ 本文由 伯乐在线 - Wing 翻译,黄利民 校稿 ...
- 谷歌浏览器下载地址 chrome最新版本 百度云地址
每次下载更新谷歌浏览器是一件很蛋疼的事情.百度搜索"谷歌浏览器下载地址",居然有很多骗子网站,相信有很多不知所以的人中招了.收集了一些chrome的安装包,放在了百度云里面(打不开 ...
- [JS]笔记13之Date对象
-->获取与设置时间的方法-->使用Date对象制作相应的效果 1.设置时间创建一个时间对象 new Date(time); 设置时间 time 从1970年1月1日至几种格式:new D ...
- iOS多图片下载
iOS多图片下载.在cell里面下载图片.做了缓存优化. (app.icon是图片地址) // 先从内存缓存中取出图片 UIImage *image = self.images[app.icon]; ...
- SharePoint 2013 页面访问,Url中间多一段"_layouts/15/start.aspx#"
问题描述: 我想访问如下页面 http://Host/_layouts/15/ManageFeatures.aspx 点击以后页面地址没有错,但是中间多了一段“_layouts/15/start.as ...
- Android Touch事件分发机制学习
Android 事件分发机制 ViewGroup dispatchTouchEvent 返回true dispatchTouchEvent: Activity ACTION_DOWN Myrelat ...
- 会话技术( Cookie ,Session)
会话技术: 会话:浏览器访问服务器端,发送多次请求,接受多次响应.直到有一方断开连接.会话结束. 解决问题:可以使用会话技术,在一次会话的多次请求之间共享数据. ...
- NSLog 占位符
转自:http://blog.sina.com.cn/s/blog_75f190280101dmj8.html [iOS]Objective-C占位符使用 (2013-10-21 10:24:16) ...