2-2-06 函数-作用域-全局和局部

作用域

作用域,可以理解为一块空间,这块空间的数据是可以共享的。通俗点来说,作用域就类似于一个房子,房子中的东西归里面的所有人共享,其他房子的人无法获取。

4.1 函数为作用域

Python以函数为作用域,所以在函数内创建的所有数据,可以此函数中被使用,无法在其他函数中被使用。

# 这是一个独立的区域
def func():
    name = "武沛齐"
    data_list = [11,22,33,44]
    print(name,data_list)
    age = 20
    print(age)
# 这是一个独立的区域
def handler():
    age = 18
    print(age)

func()
handler()

python中是以函数为作用域

def func():
    name = "武沛齐"
    age = 29
    print(age)
    data_list = [11,22,33,44]
    print(name,data_list)
    
    for num in range(10):
        print(num)
        
    print(num)
    # 永远是TURE,默认建立了value的变量,但是如果不成立的,如果最后print这个value,程序会报错
    if 1 == 1:
        value = "admin"
        print(value)
	print(value)

	# 这个案例不成立,导致max_num变量不执行,print(max_num)就会报错
    if 1 > 2:
        max_num = 10
        print(max_num)
	print(max_num)
    

def handler():
    age = 18
    print(age)

handler()
func()

4.2 全局和局部

Python中以函数为作用域,函数的作用域其实是一个局部作用域。

image

# 全局变量(变量名大写)
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    # 局部变量
    url = "http://www.xxx.com"
    ...
    
def upload():
    file_name = "rose.zip"
    ...

全局作用域中创建的变量称之为【全局变量】,可以在全局作用域中被使用,也可以在其局部作用域中被使用
def定义的函数时局部变量,而开头的是定义的全局变量

寻找的顺序为:优先在局部作用域中寻找,如果没有则去上级作用域中寻找

注意:全局变量一般都是大写。

  1. 在局部作用域中读取全局作用域的变量。
  2. 但是在全局中只能找全局变量,不能找局部变量

局部作用域和全局作用域变量同名,这算啥?

# 如果全局和局部同名,局部中的print 是优先看局部中,没有后,才看全局中

COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    url = "http://www.xxx.com"
    CITY_LIST = ["河北","河南","山西"]
    print(url)
    print(COUNTRY)
    print(CITY_LIST)
    
def upload():
    file_name = "rose.zip"
    print(COUNTRY)
    print(CITY_LIST)
    
print(COUNTRY)
print(CITY_LIST)
download()
upload()
#如果全局中更新了同名变量,全局中看更新后的变量信息
COUNTRY = "中华人民共和共国"
CITY_LIST = [11,22,33]

download()
upload()

# 输出
中国
["北京","上海","深圳"]
http://www.xxx.com
中国
["河北","河南","山西"]
中国
 ["北京","上海","深圳"]
http://www.xxx.com

# 更新后

中华人民共和共国
["河北","河南","山西"]
中华人民共和共国
[11,22,33]

4.3 global关键字

![[assets/Pasted image 20221017211829.png]]

默认情况下,在局部作用域对全局变量只能进行:读取和修改内部元素(可变类型),无法对全局变量进行重新赋值。

  • 读取
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    url = "http://www.xxx.com"
    print(COUNTRY)
    print(CITY_LIST)
    
download()
  • 修改内部元素(可变类型)
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    url = "http://www.xxx.com"
    print(CITY_LIST)
    
    CITY_LIST.append("广州")
    CITY_LIST[0] = "南京"
    print(CITY_LIST)
    
download()
  • 无法对全局变量重新赋值
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    url = "http://www.xxx.com"
    # 不是对全部变量赋值,而是在局部作用域中又创建了一个局部变量 CITY_LIST 。
    CITY_LIST =  ["河北","河南","山西"]
    print(CITY_LIST)

def upload():
    file_name = "rose.zip"
    print(COUNTRY)
    print(CITY_LIST)
    
download()
upload()

如果想要在局部作用域中对全局变量重新赋值,则可以基于 global关键字实现

COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]

def download():
    url = "http://www.xxx.com"
	# 在局部作用域中强制给全局变量重新赋值
    global CITY_LIST
    CITY_LIST =  ["河北","河南","山西"]
    print(CITY_LIST)  #  ["河北","河南","山西"]
    
    global COUNTRY
    COUNTRY = "中华人民共和国"
    print(COUNTRY)   # "中华人民共和国"

def upload():
    file_name = "rose.zip"
    print(COUNTRY)    # "中华人民共和国"
    print(CITY_LIST)  # ["河北","河南","山西"]
    
download()
upload()

4.4 nolocal 关键字

改变上一级中的变量

name = 'root'


def outer():
    name = "武沛齐"

    def inner():
        nonlocal name
        name = 123

    inner()
    print(name)


outer()
print(name)

补充

打印的时机是不同额,内存地址发生变化导致不同的结果出现

第5题中的 v1和v3变量指向的都是函数内部维护的那个列表的内存地址。  
    先print(v1)时,函数内部维护的列表的值当时是{1: 2}  
    最后print(v3)时,函数内部维护的列表的值已被修改为{1: 2, 5: 6}  
  
第5题中的 v1和v3变量也是指向的都是函数内部维护的那个列表的内存地址。  
    最后再print v1和v3 时,结果就是最终函数内部维护的列表的值,即: {1: 2, 5: 6}

判断类型:

ef func():  
    return 1, 2, 3  
  
val = func()  
print( type(val) == tuple) # True  
print( type(val) == list) # False  
print( type(val) == dict) # False

案例:

  1. 根据要求实现资源下载器。

    • 启动后,让用户选择专区,每个专区用单独的函数实现,提供的专区如下:

      • 下载 花瓣网图片专区
      • 下载 抖音短视频专区
      • 下载 NBA锦集 专区
    • 在用户选择了某个功能之后,表示进入某下载专区,在里面循环提示用户可以下载的内容选项(已下载过的则不再提示下载)
      提醒:可基于全部变量保存已下载过得资源。

    • 在某个专区中,如果用户输入(Q/q)表示 退出上一级,即:选择专区。

    • 在选择专区如果输入Q/q则退出整个程序。

    • 每个专区实现下载的案例如下:

      • 图片

        # 可供用户下载的图片如下
        image_dict = {
            "1":("吉他男神","https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
            "2":("漫画美女","https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
            "3":("游戏地图","https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
            "4":("alex媳妇","https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
        }
        
        # 下载图片示例
        import request
        
        res = requests.get(
            url="https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz",
            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"
            }
        )
        
        with open("alex媳妇.png",mode="wb") as f:
            f.write(res.content)
        
      • 短视频

        # 可供用户下载的短视频如下
        video_dict = {
        	"1":{"title":"东北F4模仿秀",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
        	"2":{"title":"卡特扣篮",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
        	"3":{"title":"罗斯mvp",'url':"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
        }
        
        # 下载视频示例
        import requests
        
        res = requests.get(
            url="https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg",
            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"
            }
        )
        with open('罗斯mvp.mp4', mode='wb') as f:
            f.write(res.content)
        
      • NBA

        # 可供用户下载的NBA视频如下
        nba_dict = {
            "1":{"title":"威少奇才首秀三双","url":"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
            "2":{"title":"塔图姆三分准绝杀","url":"https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}
        }
        
        # 下载示例
        import requests
        
        res = requests.get(
            url="https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0",
            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"
            }
        )
        with open('塔图姆三分准绝杀.mp4', mode='wb') as f:
            f.write(res.content)
        

答案:


import requests

SELECTED_IMAGE_SET = set()  # 已下载图片ID(序号)
SELECTED_VIDEO_SET = set()
SELECTED_NBA_SET = set()


def download(file_path, 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"
        }
    )
    with open(file_path, mode='wb') as f:
        f.write(res.content)


def download_image():
    total_image_dict = {
        "1": ("吉他男神", "https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
        "2": ("漫画美女", "https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
        "3": ("游戏地图", "https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
        "4": ("alex媳妇", "https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
    }
    while True:
        # 构造 1.吉他男神;2.漫画美女;
        text_list = []
        for num, item in total_image_dict.items():
            if num in SELECTED_IMAGE_SET:
                continue
            data = "{}.{}".format(num, item[0])
            text_list.append(data)
        if text_list:
            text = ";".join(text_list)
        else:
            text = "无可下载选项"
        # 输出:1.吉他男神;2.漫画美女;3.游戏地图;4.alex媳妇
        print(text)

        # 返回上一步
        index = input("请输入要选择的序号(Q/q退出):")
        if index.upper() == "Q":
            return

        # 选择序号 3
        if index in SELECTED_IMAGE_SET:
            print("已下载,无法再继续下载,请重新选择!")
            continue

        group = total_image_dict.get(index)
        if not group:
            print("序号不存在,请重新选择")
            continue

        # 下载图片
        file_path = "{}.png".format(group[0])
        download(file_path, group[1])

        # 已下载集合中
        SELECTED_IMAGE_SET.add(index)


def download_video():
    total_video_dict = {
        "1": {"title": "东北F4模仿秀",
              'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
        "2": {"title": "卡特扣篮",
              'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
        "3": {"title": "罗斯mvp",
              'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
    }

    while True:
        text_list = []
        for num, item in total_video_dict.items():
            if num in SELECTED_VIDEO_SET:
                continue
            data = "{}.{}".format(num, item["title"])
            text_list.append(data)
        if text_list:
            text = ";".join(text_list)
        else:
            text = "无可下载选项"
        print(text)
        index = input("请输入要选择的序号(Q/q退出):")
        if index.upper() == "Q":
            return

        if index in SELECTED_VIDEO_SET:
            print("已下载,无法再继续下载,请重新选择!")
            continue

        group = total_video_dict.get(index)
        if not group:
            print("序号不存在,请重新选择")
            continue

        file_path = "{}.mp4".format(group["title"])
        download(file_path, group["url"])

        SELECTED_VIDEO_SET.add(index)


def download_nba():
    total_nba_dict = {
        "1": {"title": "威少奇才首秀三双",
              "url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
        "2": {"title": "塔图姆三分准绝杀",
              "url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}

    }
    while True:
        text_list = []
        for num, item in total_nba_dict.items():
            if num in SELECTED_NBA_SET:
                continue
            data = "{}.{}".format(num, item["title"])
            text_list.append(data)
        if text_list:
            text = ";".join(text_list)
        else:
            text = "无可下载选项"
        print(text)
        index = input("请输入要选择的序号(Q/q退出):")
        if index.upper() == "Q":
            return

        if index in SELECTED_NBA_SET:
            print("已下载,无法再继续下载,请重新选择!")
            continue

        group = total_nba_dict.get(index)
        if not group:
            print("序号不存在,请重新选择")
            continue

        file_path = "{}.mp4".format(group["title"])
        download(file_path, group["url"])

        SELECTED_NBA_SET.add(index)


print("欢迎使用xxx系统")
func_dict = {
    "1": download_image,
    "2": download_video,
    "3": download_nba
}
while True:
    print("1.花瓣网图片专区;2.抖音短视频专区;3.NBA锦集专区 ")
    choice = input("请选择序号:")
    if choice.upper() == "Q":
        break
    func = func_dict.get(choice)
    if not func:
        print("输入错误,请重新选择!")
        continue
    # 进入专区
    func()

简便答案:


import requests

DB = {
    "1": {
        "area": "花瓣网图片专区",
        "total_dict": {
            "1": ("吉他男神", "https://hbimg.huabanimg.com/51d46dc32abe7ac7f83b94c67bb88cacc46869954f478-aP4Q3V"),
            "2": ("漫画美女", "https://hbimg.huabanimg.com/703fdb063bdc37b11033ef794f9b3a7adfa01fd21a6d1-wTFbnO"),
            "3": ("游戏地图", "https://hbimg.huabanimg.com/b438d8c61ed2abf50ca94e00f257ca7a223e3b364b471-xrzoQd"),
            "4": ("alex媳妇", "https://hbimg.huabanimg.com/4edba1ed6a71797f52355aa1de5af961b85bf824cb71-px1nZz"),
        },
        "ext": "png",
        "selected": set()
    },
    "2": {
        "area": "抖音短视频专区",
        "total_dict": {
            "1": {"title": "东北F4模仿秀",
                  'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"},
            "2": {"title": "卡特扣篮",
                  'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"},
            "3": {"title": "罗斯mvp",
                  'url': "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg"},
        },
        "ext": "mp4",
        "selected": set()
    },
    "3": {
        "area": "NBA锦集专区",
        "total_dict": {
            "1": {"title": "威少奇才首秀三双",
                  "url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300fc20000bvi413nedtlt5abaa8tg&ratio=720p&line=0"},
            "2": {"title": "塔图姆三分准绝杀",
                  "url": "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0d00fb60000bvi0ba63vni5gqts0uag&ratio=720p&line=0"}
        },
        "ext": "mp4",
        "selected": set()
    },
}


def download(file_path, 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"
        }
    )
    with open(file_path, mode='wb') as f:
        f.write(res.content)


def handler(area_info):
    # 进入专区提醒
    summary = "欢迎进入{}".format(area_info['area'])
    print(summary)

    # 专区中选择下载
    while True:
        text_list = []
        for num, item in area_info['total_dict'].items():
            if num in area_info['selected']:
                continue
            if type(item) == tuple:
                data = "{}.{}".format(num, item[0])
            else:
                data = "{}.{}".format(num, item["title"])
            text_list.append(data)
        if text_list:
            text = ";".join(text_list)
        else:
            text = "无可下载选项"

        print(text)
        index = input("请输入要选择的序号(Q/q退出):")
        if index.upper() == "Q":
            return

        if index in area_info['selected']:
            print("已下载,无法再继续下载,请重新选择!")
            continue

        group = area_info['total_dict'].get(index)
        if not group:
            print("序号不存在,请重新选择")
            continue

        if type(group) == tuple:
            title, url = group
        else:
            title, url = group['title'], group['url']

        file_path = "{}.{}".format(title, area_info['ext'])
        download(file_path, url)

        area_info['selected'].add(index)


print("欢迎使用xxx系统")
while True:
    print("1.花瓣网图片专区;2.抖音短视频专区;3.NBA锦集 专区 ")
    choice = input("请选择序号(Q/q退出):")
    if choice.upper() == "Q":
        break

    # 选择序号: 去db中找对应的字典信息
    area_dict = DB.get(choice)

    if not area_dict:
        print("输入错误,请重新选择!")
        continue

    # 进入专区(area_dict选择的专区信息)
    handler(area_dict)


posted @ 2022-10-19 09:44  布丁家的苏苏  Views(19)  Comments(0)    收藏  举报