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


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



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


# name='alex'
# def func():
#     name='egon'
#     x=1000000000000000000000
#     def bar():
#         print(name)
#         print(x)
#         a=1
#         b=2
#     return bar
#
# f=func()
# print(f())
# 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()


#包一层
# 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()#index()
#         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
# @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)