Python开发基础 day6 装饰器

(一)闭包函数

闭包函数:函数内部定义函数,成为内部函数,
该内部函数包含对外部作用域,而不是对全局作用域名字的引用
那么该内部函数成为闭包函数

# name='alex'
# def func():
# name='egon'
# def bar():
# print(name)
# return bar
#
#
# b=func()
# print(b)
# name='hahahahahahahahahahahahahahahhahahah'


 

 

# def foo():
# name='ssssssssssssssssssssssssssssssssssssssss'
# b()
#
# foo()

 


# name='alex'
# def func():
# name='egon'
# def bar():
# print(name)
# return bar
#
# f=func()

 

 

# name='alex'
# def func():
# name='egon'
# x=1000000000000000000000
# def bar():
# print(name)
# print(x)
# a=1
# b=2
# return bar
# #
# f=func()
#
# # print(f.__closure__[0].cell_contents)
# print(f.__closure__[1].cell_contents)


# name='alex'
# def func():
# name='egon'
# x=1000000000000000000000
# def bar():
# print(name)
# print(x)
# a=1
# b=2
# print(bar.__closure__)

# func()

闭包函数:1 内部函数 2 包含对外部作用域而非全局作用域的引用
闭包函数的特点:
 自带作用域
 延迟计算

# name='alex'
# def func():
# def bar():
# print(name)
# return bar
#
# f=func()
# print(f.__closure__)
#
# f()

#
#
# money=1000
# def tell_ino(name):
# print('%s have money %s' %(name,money))
#
# tell_ino('egon')
#
# def f1():
# money=10
# tell_ino('egon')
#
# f1()

#
# money=1000
# def f1():
# money=10
# def tell_ino(name):
# print('%s have money %s' %(name,money))
# tell_ino('egon')
#
# f1()

 


#包一层
def wrapper():
money=1000
def tell_info():
print('egon have money %s' %(money))
return tell_info

tell_info=wrapper()

def foo():
money=100
tell_info()

# foo()


#包两层

# def aaa():
# name='egon'
# def wrapper():
# money=1000
# def tell_info():
# print('egon have money %s' %(money))
# print('my namn is %s' %name)
# return tell_info
# return wrapper
#
# w=aaa()
# tell_info=w()
# print(tell_info.__closure__[0].cell_contents)
# print(tell_info.__closure__[1].cell_contents)


'''
报错NameError: name 'money' is not defined

原因:
函数的作用域关系在函数定义阶段就已经固定,与调用位置无关
无论函数在何处调用,都需要回到定义阶段去找对应的作用域关系
此例:虽然tell_info('egon')是在foo内调用并且引用money,但仍需要回到定义
tell_info的阶段去找作用域关系,而定义时tell_info引用的money就是全局的money
如果全局不存在则抛出异常NameError

'''


#定义闭包函数的基本形式


# def 外部函数名():
# 内部函数需要的变量
# def 内部函数():
# 引用外部变量
# return 内部函数

# def deco():
# x=1
# def wrapper():
# print(x)
#
# return wrapper
#
# wrapper=deco()
#
# print(wrapper)

 

 

# def wrapper():
# print(x)
# print(y)

# def deco1():
# y=2
# def deco():
# x=1
# def wrapper():
# print(x)
# print(y)
#
# return wrapper
# return deco
#
#
#
# deco=deco1()
#
# wrapper=deco()
#
#
#
#
#
# wrapper()


from urllib.request import urlopen

# print(urlopen('http://www.xiaohua100.cn/').read())
# print(urlopen('https://www.python.org').read())

# def get(url):
# return urlopen(url).read()
#
#
# print(get('http://www.xiaohua100.cn/'))

def index(url):
# url='http://www.xiaohua100.cn/'
def get():
return urlopen(url).read()
return get


xiaohua=index('http://www.xiaohua100.cn/')

 

python=index('https://www.python.org')


baidu=index('http://www.baidu.com')


print(python())

(二)装饰器

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

二:装饰器,装饰器本质可以任意可调用对象,被装饰的对象也可以是任意
可调用对象,
装饰器的功能是:
在不修改被装饰对象源代码以及调用方式的前提下为期添加新功能

原则:
1.不修改源代码
2.不修改调用方法
目标:添加新功能

 

'''

# import time
# import random
# #装饰器
# def timmer(func):
# # func=index
# def wrapper():
# start_time = time.time()
# func() #index()
# stop_time=time.time()
# print('run time is %s' %(stop_time-start_time))
# return wrapper
# #被装饰函数
# def index():
# time.sleep(random.randrange(1,5))
# print('welecome to index page')
#
# def home():
# time.sleep(random.randrange(1,3))
# print('welecome to HOME page')
#
# index=timmer(index) #index=wrapper
# home=timmer(home)
#
# index() #wrapper()
# home()

 

#装饰器的语法:在被装饰对象的正上方的单独一行,@装饰器名字
# import time
# import random
# #装饰器
# def timmer(func):
# def wrapper():
# start_time = time.time()
# func()
# stop_time=time.time()
# print('run time is %s' %(stop_time-start_time))
# return wrapper
# #被装饰函数
# @timmer #index=timmer(index)
# def index():
# time.sleep(random.randrange(1,5))
# print('welecome to index page')
# # @timmer #home=timmer(home)
# # def home():
# # time.sleep(random.randrange(1,3))
# # print('welecome to HOME page')
#
# index() #wrapper()
# # home()

 

#加多个装饰器
import time
import random
#装饰器
def timmer(func):
def wrapper():
start_time = time.time()
func()
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return wrapper
def auth(func):
def deco():
name=input('name: ')
password=input('password: ')
if name == 'egon' and password == '123':
print('login successful')
func() #wrapper()
else:
print('login err')
return deco

#被装饰函数
@auth #index=auth(wrapper) #index=deco #index=auth(wrapper) #index=deco
@timmer #index=timmer(index) #index=wrapper
def index():
# time.sleep(random.randrange(1,5))
time.sleep(3)
print('welecome to index page')


def home():
time.sleep(random.randrange(1,3))
print('welecome to HOME page')

# index() #deco()
# home()

 

 

 


#装饰器修订
import time
import random
#装饰器
def timmer(func):
def wrapper(*args,**kwargs):
start_time = time.time()
res=func(*args,**kwargs)
stop_time=time.time()
print('run time is %s' %(stop_time-start_time))
return res
return wrapper
#被装饰函数

@timmer
def index():
time.sleep(random.randrange(1,5))
print('welecome to index page')
@timmer
def home(name):
time.sleep(random.randrange(1,3))
print('welecome to %s HOME page' %name)
return 123123123123123123123123123123123123123123


index()

 

 

 

 


res1=index()
print('index return %s' %res1)
res2=home('egon') #wraper()
print('home return %s' %res2)

编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
# 注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

# user_dic={
# 'egon':'123',
# 'alex':'alex3714',
# 'wupeiqi':'wu13',
# 'yuanhao':'123123'
# }

# with open('db.txt','w',encoding='utf-8') as f:
# f.write(str(user_dic))

#
# with open('db.txt','r',encoding='utf-8') as f:
# res=f.read()
# # print(res,type(res))
# user_dic=eval(res)
#
# print(user_dic,type(user_dic))

# db_path=r'C:UsersAdministratorPycharmProjectspython5期day8db.txt'
#
# login_dic={
# 'user':None,
# 'status':False,
# }
#
#
# def auth(func):
# def wrapper(*args,**kwargs):
# if login_dic['user'] and login_dic['status']:
# res = func(*args, **kwargs)
# return res
#
# name=input('your name: ')
# password=input('your password: ')
# with open(db_path,'r',encoding='utf-8') as f:
# user_dic=eval(f.read())
#
# if name in user_dic and password == user_dic[name]:
# print('login ok')
# login_dic['user']=name
# login_dic['status']=True
# res=func(*args,**kwargs)
# return res
# else:
# print('login err')
#
# return wrapper
#
#
# @auth #auth(index)
# def index():
# print('welecome to index')
#
# @auth
# def home(name):
# print('welecome %s to home page' %name)
#
#
# index()
#
# home('egon')

 

 

 

# dic={'x':1}
# l=[1,2,3]
# salary=1000
# def foo():
# # print(dic)
# dic['x']=2
# dic['y']=3
# l.append(4)
# global salary
# salary=0
# foo()
# print(dic)
# print(l)
# print(salary)

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

from urllib.request import urlopen
import os

cache_path=r'C:UsersAdministratorPycharmProjectspython5期day8cache.txt'
def make_cache(func):
def wrapper(*args,**kwargs):
if os.path.getsize(cache_path):
#有缓存
print('33[45m=========>有缓存33[0m')
with open(cache_path,'rb') as f:
res=f.read()

else:
res=func(*args,**kwargs) #下载
with open(cache_path,'wb') as f: #制作缓存
f.write(res)

return res

return wrapper

@make_cache
def get(url):
return urlopen(url).read()


# print('================>first')
# print(get('https://www.python.org'))
# print('================>second')
# print(get('https://www.python.org'))
# print('================>third')
# print(get('https://www.python.org'))


#缓存多个不同网站的内容:
#思路:hash每个url,用得到的值做成文件名,一个网站一个文件名,
# 然后每次根据传进来的url进行hash得到的结果去寻找文件

#
# s='hello 123'
# print(hash(s))
# s='hello 123'
# print(hash(s))

 

 

 

#
# def f1():
# print('from f1')
#
#
# def f2():
# print('from f2')
#
# def f3():
# print('from f3')
#
# func_dic={
# 'f1':f1,
# 'f2':f2,
# 'f3':f3
# }
#
# while True:
# cmd=input('>>:').strip()
# if cmd in func_dic:
# func_dic[cmd]()

 

func_dic={}

def deco(key):
def deco2(func):
func_dic[key]=func
return deco2

@deco('f1')
def f1():
print('from f1')

@deco('f2')
def f2():
print('from f2')
@deco('f3')
def f3():
print('from f3')


print(func_dic)

while True:
cmd=input('>>:').strip()
if cmd in func_dic:
func_dic[cmd]()
原文地址:https://www.cnblogs.com/bsxq/p/7009099.html