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. ...
随机推荐
- python征程3.0(python对象)
1.python使用对象模型来存储数据.构造任何类型的值都是一个对象.”尽管python被当成一种面向对象的脚本的编程语言“,但你完全能够写出不使用任何类和实例的脚本. python对象都拥有三个特性 ...
- 从零开始学 Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- java web学习总结(八) -------------------HttpServletResponse对象(二)
一.HttpServletResponse常见应用--生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类,
- 《对象及DOM知识点及其应用1》
1.图片间的来回切换用if{}else{}; <超链接方式的切换图片(常用)>如:<a href="../images1/1-small.jpg" id=&quo ...
- jQuery ClockPicker 圆形时钟
ClockPicker.js是一款时钟插件,其实还可以改进,里面的分可以改成短横线. 在线实例 实例预览 jQuery ClockPicker 圆形时钟 使用方法 <div class=&qu ...
- JS 预解释相关理解
1.JS中的内存空间分为两种:栈内存.堆内存 栈内存:提供JS代码执行的环境;存储基本数据类型的值; ->全局作用域或者私有的作用域其实都是栈内存 堆内存:存储引用数据类型的值(对象是把属性名和 ...
- jquery定时滑出可最小化的底部提示层
效果预览:http://keleyi.com/keleyi/phtml/jqtexiao/index.htm当打开页面或者刷新页面后等待两秒钟,会在底部滑出可最小化的提示层.滑出层半透明,可关闭再现. ...
- kail linux 虚拟机安装实录(一) 新建虚拟机
各位晚上好. 现在开始进行kail linux 在虚拟机上的安装. 我所使用的工具如下: kail linux 2.0 x64 http://mirrors.neusoft.edu.cn/kal ...
- 用UILocalNotification实现一个闹钟(Swift)
之前项目需求要实现一个闹钟,github上找了半天发现都是很旧的代码了,所以就准备自己写一个,刚好最近在学习Swift,就用Swift写了一个demo放在这里:https://github.com/P ...
- Xcode出现( linker command failed with exit code 1)错误总结
这种问题,通常出现在添加第三方库文件或者多人开发时. 这种问题一般是找不到文件而导致的链接错误. 我们可以从如下几个方面着手排查. 先可以再试试一下几个方法: 1,看看是不是有新添加的文件跟之前文件 ...