#  1、函数作用域
NAME = '张学友'
print(NAME)

def func():
    print(NAME)  # 函数会优先在自身内部作用域里找变量值,如找不到,则前往上一级找
func()

#  2、函数如果后面改动,则改动前按照原函数,改动后的按照改动后的函数
def func():
    print(123)

func()  # 输出123

def func():
    print(333)

def func2():
    func()
func2()  # 输出333


#  3、闭包:封装数据防止污染全局;封装数据到一个包里,使用时可以提取
def func(age):
    name = 'alen'
    def func_1():
        print(name,age)

    def func_2():
        print(name*2,age+2)

    def func_3():
        print(name*3,age+3)
    func_1()  # alen 18
    func_2()  # alenalen 20
    func_3()  # alenalenalen 21



#  4、闭包的应用场景案例:完成串行下载
import requests
from concurrent.futures.thread import ThreadPoolExecutor

def download_video(url):
    res = requests.get(
        url=url,
        headers={
            "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 FS"
        }
    )
    return res.content


def outer(file_name):
    def write_file(response):
        content = response.result()
        with open(file_name, mode='wb') as file_object:
            file_object.write(content)

    return write_file

#  线程池
POOL = ThreadPoolExecutor(10)

video_dict = [
    ("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),
    ("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),
    ("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]
for item in video_dict:
    future = POOL.submit(download_video, url=item[1])
    future.add_done_callback(outer(item[0]))

POOL.shutdown()


#  5、装饰器(重点)
#  python特殊语法:在某个函数上方加上’@函数名‘,python内部会自动执行函数名,并把下方函数当作参数传递,执行完之后,再将结果赋值给下方函数
def outer(origal):   # outer(fun_01)
    def inner():
        print('我是func函数')
        res = origal()  # res = fun_01()
        print(('adfads'))
        return res  # 返回fun_01()
    return inner

@outer  # fun_01 = outer(fun_01)
def fun_01():
    print('您好!')
    value = (11, 22, 33, 44)
    return value
r = fun_01()
print(r)

# outer函数引用fun_01函数作为参数并执行,随后,返回inner函数,fun_01函数等于inner函数,执行后导出打印值,最后由于inner返回值是res,res等
# 于fun_01的执行值,返回value,因此最后打印值是value值