一.装饰器

1.知识储备

函数对象

    函数可以被引用

函数可以当参数传递

返回值可以是函数

可以当作容器的元素

def func1():
print (666)
def func2():
print (666)
def func3():
print (666)
list1=[func1,func2,func3]
for i in list1:
i()

*args:接收溢出的位置参数

  **kwargs:接收溢出的关键字参数

名称空间与作用域

2.闭包函数

闭包函数的定义:定义在函数内部的函数,特点是:包含对外部作用域而不是全局作用域名字的引用。这个函数就称为闭包函数。

  闭包函数的两个特征:内部函数要引用外部函数的变量,外部函数的返回值是内部函数。

  例子:

  

  当函数内部需要一个变量的时候,有两种方式给函数传入变量,

  第一种:为函数添加一个参数。

  第二种:把这个函数变成闭包函数,也就是在函数外部添加一个函数。把变量写在外部函数内,或者当作参数传给外部函数。将内部函数的函数名return一下,这样内部函数就被外部函数包起来了。

  闭包特性:python遇到闭包,不会释放名称空间。

3.装饰器

为什么要用装饰器?

开放封闭原则:对扩展是开放的,对修改是关闭的

                   1. 不修改被装饰对象的源代码           2. 不修改被装饰对象的调用方式。

装饰器的目标:在遵循1和2的前提下,为被装饰器对象添加上新功能

什么是装饰器?

    装饰他人的器具,本身可以任意可调用对象,被装饰者也可以是任意可调用对象。

   带参数的装饰器,怎么写?

4.练习题:

一,编写函数,(函数的执行时间是随机的)

import time
def a():
x = time.strftime('%Y-%m-%d %X')
print(x)
a()

结果:

D:\Python36\python.exe F:/python/第一课/while-lianxi.py
2017-10-14 08:40:11

二,编写装饰器,为函数加上统计时间的功能。


#这种是采用传参的方式,虽然没有修改index和home函数的源代码,但是修改了它们的调用方式。所以需要采用装饰器。
import time
def timmer(tongji_hanshu):
# tongji_hanshu=home
def inner():
start_time=time.time()
tongji_hanshu()
stop_time=time.time()
print("函数执行时间: %s" %(stop_time-start_time))
return inner
@timmer #语法糖
def index():
time.sleep(3)
print("welcome to index page!")
index()
@timmer
def home():
time.sleep(5)
print("welcome to home page!")
home()

结果:

D:\Python36\python.exe F:/python/第一课/while-lianxi.py
welcome to index page!
函数执行时间: 3.0001718997955322
welcome to home page!
函数执行时间: 5.000285863876343

三. 编写装饰器,为函数加上认证的功能。

import time
def outter(func):
def auth():
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
if username=='yangjianbo' and password=='':
print ("登录成功!")
func() #这么写死了
else:
print("登录失败!")
return auth
@outter
def index():
time.sleep(3)
print("welcome to index page!")
index()

结果:

D:\Python36\python.exe F:/python/第一课/while-lianxi.py
输入用户名: yangjianbo
输入密码: 123
登录成功!
welcome to index page!

四:编写装饰器,为多个函数加上认证功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码。

#这种情况是针对index,没有参数的函数,如果被装饰的函数有参数,如何修订装饰器。
import time
def outter(func):
def auth(*args,**kwargs):
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
if username=='yangjianbo' and password=='':
print ("登录成功!")
func(*args,**kwargs) #这么写死了
else:
print("登录失败!")
return auth
@outter
def index():
time.sleep(3)
print("welcome to index page!")
index()
@outter #home=outter(home)
def home(username):
time.sleep(2)
print("welcome %s to home page!" %username)
home('yangjianbo')

结果:

D:\Python36\python.exe F:/python/第一课/while-lianxi.py
输入用户名: yangjianbo
输入密码: 123
登录成功!
welcome to index page!
输入用户名: yangjianbo
输入密码: 123
登录成功!
welcome yangjianbo to home page!

根据题目要求:只要登录成功,以后就不需要再登录。所以上面的代码还需要修改。

import os
import time
login_status=False
def outter(func):
def auth(*args,**kwargs):
if login_status is True:
return func(*args,**kwargs)
else:
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
with open('account.txt','r',encoding='utf-8') as accout:
accout=accout.read().strip('\r\n').split('|')
if username==accout[0] and password==accout[1]:
print ("登录成功!")
login_status=True
func(*args,**kwargs)
else:
print("登录失败!")
return auth
@outter #index=outter(index)
def index():
time.sleep(3)
print("welcome to index page!")
index() @outter
def home(username):
time.sleep(2)
print("welcome %s to home page!" %username)
home('yangjianbo')

结果:

D:\Python36\python.exe F:/python/第一课/while-lianxi.py
Traceback (most recent call last):
File "F:/python/第一课/while-lianxi.py", line 158, in <module>
index()
File "F:/python/第一课/while-lianxi.py", line 140, in auth
if login_status is True:
UnboundLocalError: local variable 'login_status' referenced before assignment

上面报错的分析:说局部变量login_status在引用之前没有指定.

我明明定义在全局作用域了,为什么报错?

解决方法:在函数内,添加一个关键字global,表示引用全局变量。

修改后的代码:

import os
import time
login_status=False
def outter(func):
def auth(*args,**kwargs):
global login_status
if login_status is True:
return func(*args,**kwargs)
else:
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
with open('account.txt','r',encoding='utf-8') as accout:
accout=accout.read().strip('\r\n').split('|')
if username==accout[0] and password==accout[1]:
print ("登录成功!")
login_status=True
func(*args,**kwargs)
else:
print("登录失败!")
return auth
@outter #index=outter(index)
def index():
time.sleep(3)
print("welcome to index page!")
index() @outter
def home(username):
time.sleep(2)
print("welcome %s to home page!" %username)
home('yangjianbo')

结果:没有报错了。

第四个装饰器最后版本:

import time
user_status={"user":None,"login_status":False}
def outter(func):
def auth(*args,**kwargs):
if user_status['user'] and user_status['login_status']:
res=func(*args, **kwargs)
return res
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
if username=='yangjianbo' and password=='123':
print ("登录成功!")
user_status['user']=username
user_status['login_status']=True
res=func(*args, **kwargs)
return res
else:
print("登录失败!")
return auth
@outter
def index():
time.sleep(3)
print("welcome to index page!")
# return 123
index()
@outter
def home(username):
time.sleep(2)
print("welcome to %s home page" % username)
# return 456 home('yangjianbo')

 练习五  编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

import time
import random
user={"user":None,"login_time":None,'timeout':0.03} def timmer(func):
def inner(*args,**kwargs):
start_time=time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('%s' %(stop_time-start_time))
return res
return inner
def outter(func):
def auth(*args,**kwargs):
if user['user']:
timeout=time.time()-user['login_time']
if timeout<user['timeout']:
res=func(*args, **kwargs)
return res
username=input("输入用户名: ").strip()
password=input("输入密码: ").strip()
if username=='yangjianbo' and password=='123':
user['user']=username
user['login_time']=time.time()
res=func(*args, **kwargs)
return res
else:
print("登录失败!")
return auth
@outter
def index():
time.sleep(random.randrange(3))
print("welcome to index page!") index() @outter
def home(username):
time.sleep(random.randrange(3))
print("welcome to %s home page" % username) home('yangjianbo')

  练习六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

from urllib.request import urlopen

def outer(url):
def get():
f=urlopen(url).read()
return f
return get
baidu=outer('http://www.baidu.com')
sohu=outer('http://www.sohu.com')
baidu=baidu()
sohu=sohu()

  练习七:拿到下载的页面,保存到一个文件中。

from urllib.request import urlopen

def outer(url):
def get():
f=urlopen(url).read()
return f
return get
baidu=outer('http://www.baidu.com')
sohu=outer('http://www.sohu.com')
baidu=baidu()
sohu=sohu()
with open('baidu.html','w',encoding='utf-8') as f:
f.write(baidu.decode('utf-8'))

  

六. 迭代器

可迭代对象

    内部含有'__iter__'方法的数据就是可迭代对象

    s1='abcdef'

    print (dir(s1))

    print('__iter__' in dir(s1))

迭代器对象

    内部含有'__iter__'方法并且含有'__next__'方法就是迭代器

  如何将可迭代对象转换为迭代器对象

    list1=[1,2,3,4]

    iter1=iter(list1)  #可迭代对象转换为迭代器

    print(iter1)

    print(iter1.__next__())

  迭代器的特点

    1.  非常节省内存

    2.  他满足惰性机制

    3.  一条走到黑

  利用while循环模拟for循环

    list1=[1,2,3,4]

    iter1=iter(list1)

    while 1:

      try:

        print(iter1.__next__())

      except StopIteration:

        break

七. 生成器

  自己用python代码写的迭代器

  生成器的定义:

    1.  函数式写法,构建生成器

    2.  只要函数中出现yield,那么他就不是函数了,它是生成数函数。

八.列表推导式

  凡是用列表推导式构建的数据,python代码都可以构建,列表推导式都可以构建。

  循环模式

  list1=[i for i in range(1,200)]

print (list1)

  筛选模式

九.生成器表达式

十.列表推导式与生成器表达式

  优点:构造简单,一行完成。

  缺点:不能排错

     不能构建复杂的数据结构

  

  

Python学习笔记四的更多相关文章

  1. Python学习笔记(四)Python函数的参数

    Python的函数除了正常使用的必选参数外,还可以使用默认参数.可变参数和关键字参数. 默认参数 基本使用 默认参数就是可以给特定的参数设置一个默认值,调用函数时,有默认值得参数可以不进行赋值,如: ...

  2. Python学习笔记四:面向对象编程

    一:定义类并创建实例 Python中定义类,通过class关键字,类名开头大写,参数列表为所继承的父类.如果没有需要明确继承的类,则继承object. 使用类来创建对象,只需 类名+() 形式即可,p ...

  3. python学习笔记(四) 思考和准备

    一.zip的坑 zip()函数接收多个可迭代数列,将数列中的元素重新组合,在3.0中返回迭代器指向 数列首地址,在3.0以下版本返回List类型的列表数列.我用的是3.5版本python, 所以zip ...

  4. python学习笔记(四):函数

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...

  5. python学习笔记(四):生成器、内置函数、json

    一.生成器 生成器是什么?其实和list差不多,只不过list生成的时候数据已经在内存里面了,而生成器中生成的数据是当被调用时才生成呢,这样就节省了内存空间. 1. 列表生成式,在第二篇博客里面我写了 ...

  6. 【Python学习笔记四】获取html内容之后,如何提取信息:使用正则表达式筛选

    在能够获取到网页内容之后,发现内容很多,那么下一步要做信息的筛选,就和之前的筛选图片那样 而在python中可以通过正则表达式去筛选自己想要的数据 1.首先分析页面内容信息,确定正则表达式.例如想获取 ...

  7. python学习笔记四 迭代器,生成器,装饰器(基础篇)

    迭代器 __iter__方法返回一个迭代器,它是具有__next__方法的对象.在调用__next__方法时,迭代器会返回它的下一个值,若__next__方法调用迭代器 没有值返回,就会引发一个Sto ...

  8. Python学习笔记四--字典与集合

    字典是Python中唯一的映射类型.所谓映射即指该数据类型包含哈希值(key)和与之对应的值(value)的序列.字典是可变类型.字典中的数据是无序排列的. 4.1.1字典的创建及赋值 dict1={ ...

  9. python学习笔记(四)、条件、循环及其他语句

    1 再谈print和import 1.1 打印多个参数 print 能够同时打印多个表达式,并且能自定义分隔符.如下: print('a','b','c') ——> a b c print('a ...

随机推荐

  1. C# Note37: Writing unit tests with use of mocking

    前言 What's mocking and its benefits Mocking is an integral part of unit testing. Although you can run ...

  2. P4610 [COCI2011-2012#7] KAMPANJA

    题目背景 临近选举,总统要在城市1和城市2举行演讲.他乘汽车完成巡回演讲,从1出发,途中要经过城市2,最后必须回到城市1.特勤局对总统要经过的所有城市监控.为了使得费用最小,必须使得监控的城市最少.求 ...

  3. 七牛Qshell 常用命令打印

    下载 该工具使用Go语言编写而成,当然为了方便不熟悉Go或者急于使用工具来解决问题的开发者,我们提供了预先编译好的各主流操作系统平台的二进制文件供大家下载使用,由于平台的多样性,我们把这些二进制打包放 ...

  4. LOJ #2719. 「NOI2018」冒泡排序(组合数 + 树状数组)

    题意 给你一个长为 \(n\) 的排列 \(p\) ,问你有多少个等长的排列满足 字典序比 \(p\) 大 : 它进行冒泡排序所需要交换的次数可以取到下界,也就是令第 \(i\) 个数为 \(a_i\ ...

  5. pgsql 并行相关配置

  6. mysql数据库建表的基本规范

    1.创建表的时候必须指定主键,并且主键建立后最好不要再有数据修改的需求 mysql从5.5版本开始默认使用innodb引擎,innodb表是聚簇索引表,也就是说数据通过主键聚集( 主键下存储该行的数据 ...

  7. 计算pi的位数

    from random import random from math import sqrt from time import clock DARTS=1000000 hits=0.0 clock( ...

  8. 什么是javabean及其用法(转)

    因工作需要 需要学习jsp方面的知识 这篇博客文章写得比较全面 我记录下: 一.什么是JavaBean JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: 这个Java类必须具有一个 ...

  9. Tomcat 服务器

    1 相关概念 1 软件的架构 1 c/s 客服端/服务端 2 b/s 浏览器/服务器 2 资源的分类 1 静态资源 所有用户访问后 得到的资源是一样的 称为静态资源 html css js 静态资源可 ...

  10. node.js的基础知识

    第一部分知识: .命令行窗口(小黑屏).CMD窗口.终端.shell - 开始菜单 --> 运行 --> CMD --> 回车 - 常用的指令: dir 列出当前目录下的所有文件 c ...