函数高级.

函数高级

  • 1. 函数嵌套
      • 1.1 函数在作用域中
      • 1.2 函数定义的位置
      • 1.3 嵌套引发的作用域问题
      • 练习题
    • 2.闭包
    • 3.装饰器
      • 3.1 第一回合
      • 3.2 第二回合
      • 3.3 第三回合
      • 优化
      • 伪应用场景
      • 重要补充:functools
    • 总结
    • 作业

各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料!

1. 函数嵌套

Python中以函数为作用域,在作用域中定义的相关数据只能被当前作用域或子作用域使用。

NAME = "武沛齐"
print(NAME)def func():print(NAME)func()

1.1 函数在作用域中

其实,函数也是定义在作用域中的数据,在执行函数时候,也同样遵循:优先在自己作用域中寻找,没有则向上一接作用域寻找,例如:

# 1. 在全局作用域定义了函数func
def func():print("你好")# 2. 在全局作用域找到func函数并执行。
func()# 3.在全局作用域定义了execute函数
def execute():print("开始")# 优先在当前函数作用域找func函数,没有则向上级作用域中寻找。func()print("结束")# 4.在全局作用域执行execute函数
execute()

此处,有一个易错点:作用域中的值在被调用时到底是啥?

  • 情景1

    def func():print("你好")func()def execute():print("开始")func()print("结束")execute()def func():print(666)func()
    
  • 情景2

    def func():print("你好")func()def execute():print("开始")func()print("结束")def func():print(666)func()
    execute()
    

1.2 函数定义的位置

上述示例中的函数均定义在全局作用域,其实函数也可以定义在局部作用域,这样函数被局部作用域和其子作用于中调用(函数的嵌套)。

def func():print("沙河高晓松")def handler():print("昌平吴彦祖")def inner():print("朝阳大妈")inner()func()print("海淀网友")handler()

到现在你会发现,只要理解数据定义时所存在的作用域,并根据从上到下代码执行过程进行分析,再怎么嵌套都可以搞定。

现在的你可能有疑问:为什么要这么嵌套定义?把函数都定义在全局不好吗?

其实,大多数情况下我们都会将函数定义在全局,不会嵌套着定义函数。不过,当我们定义一个函数去实现某功能,想要将内部功能拆分成N个函数,又担心这个N个函数放在全局会与其他函数名冲突时(尤其多人协同开发)可以选择使用函数的嵌套。

def f1():passdef f2():passdef func():f1()f2()
def func():def f1():passdef f2():passf1()f2()
"""
生成图片验证码的示例代码,需要提前安装pillow模块(Python中操作图片中一个第三方模块)pip3 install pillow
"""
import random
from PIL import Image, ImageDraw, ImageFontdef create_image_code(img_file_path, text=None, size=(120, 30), mode="RGB", bg_color=(255, 255, 255)):""" 生成一个图片验证码 """_letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z_upper_cases = _letter_cases.upper()  # 大写字母_numbers = ''.join(map(str, range(3, 10)))  # 数字chars = ''.join((_letter_cases, _upper_cases, _numbers))width, height = size  # 宽高# 创建图形img = Image.new(mode, size, bg_color)draw = ImageDraw.Draw(img)  # 创建画笔def get_chars():"""生成给定长度的字符串,返回列表格式"""return random.sample(chars, 4)def create_lines():"""绘制干扰线"""line_num = random.randint(*(1, 2))  # 干扰线条数for i in range(line_num):# 起始点begin = (random.randint(0, size[0]), random.randint(0, size[1]))# 结束点end = (random.randint(0, size[0]), random.randint(0, size[1]))draw.line([begin, end], fill=(0, 0, 0))def create_points():"""绘制干扰点"""chance = min(100, max(0, int(2)))  # 大小限制在[0, 100]for w in range(width):for h in range(height):tmp = random.randint(0, 100)if tmp > 100 - chance:draw.point((w, h), fill=(0, 0, 0))def create_code():"""绘制验证码字符"""if text:code_string = textelse:char_list = get_chars()code_string = ''.join(char_list)  # 每个字符前后以空格隔开# Win系统字体# font = ImageFont.truetype(r"C:\Windows\Fonts\SEGOEPR.TTF", size=24)# Mac系统字体# font = ImageFont.truetype("/System/Library/Fonts/SFNSRounded.ttf", size=24)# 项目字体文件font = ImageFont.truetype("MSYH.TTC", size=15)draw.text([0, 0], code_string, "red", font=font)return code_stringcreate_lines()create_points()code = create_code()# 将图片写入到文件with open(img_file_path, mode='wb') as img_object:img.save(img_object)return codecode = create_image_code("a2.png")
print(code)

1.3 嵌套引发的作用域问题

基于内存和执行过程分析作用域。

name = "武沛齐"def run():name = "alex"def inner():print(name)inner()run()

在这里插入图片描述

name = "武沛齐"def run():name = "alex"def inner():print(name)return innerv1 = run()
v1()v2 = run()
v2()

在这里插入图片描述

name = "武沛齐"def run():name = "alex"def inner():print(name)return [inner,inner,inner]func_list = run()
func_list[2]()
func_list[1]()funcs = run()
funcs[2]()
funcs[1]()

在这里插入图片描述

三句话搞定作用域:

  • 优先在自己的作用域找,自己没有就去上级作用域。
  • 在作用域中寻找值时,要确保此次此刻值是什么。
  • 分析函数的执行,并确定函数作用域链。(函数嵌套)

练习题

  1. 分析代码,写结果

    name = '武沛齐'def func():def inner():print(name)res = inner()return resv = func()
    print(v)# 武沛齐
    # None
    
  2. 分析代码,写结果

    name = '武沛齐'def func():def inner():print(name)return "alex"res = inner()return resv = func()
    print(v)# 武沛齐
    # alex
    
  3. 分析代码,写结果

    name = 'root'def func():def inner():print(name)return 'admin'return innerv = func()
    result = v()
    print(result)# root
    # admin
    
  4. 分析代码,写结果

    def func():name = '武沛齐'def inner():print(name)return '路飞'return innerv11 = func()
    data = v11()
    print(data)v2 = func()()
    print(v2)
    
  5. 分析代码,写结果

    def func(name):# name="alex"def inner():print(name)return 'luffy'return innerv1 = func('武沛齐')()
    print(v1)v2 = func('alex')()
    print(v2)
    

    在这里插入图片描述

    def func(name):def inner():print(name)return 'luffy'return innerv1 = func('武沛齐')
    v2 = func('alex')
    v1()
    v2()
    

    在这里插入图片描述

  6. 分析代码,写结果

    def func(name=None):if not name:name= '武沛齐'def inner():print(name)return 'root'return innerv1 = func()()
    v2 = func('alex')()
    print(v1,v2)# 武沛齐
    # alex
    # root root
    

    在这里插入图片描述

2.闭包

闭包,简而言之就是将数据封装在一个包(区域)中,使用时再去里面取。(本质上 闭包是基于函数嵌套搞出来一个中特殊嵌套)

  • 闭包应用场景1:封装数据防止污染全局。

    name = "武沛齐"def f1():print(name, age)def f2():print(name, age)def f3():print(name, age)def f4():pass
    
    def func(age):name = "武沛齐"def f1():print(name, age)def f2():print(name, age)def f3():print(name, age)f1()f2()f3()func(123)
    
  • 闭包应用场景2:封装数据封到一个包里,使用时在取。
    在这里插入图片描述

    def task(arg):def inner():print(arg)return innerv1 = task(11)
    v2 = task(22)
    v3 = task(33)
    v1()
    v2()
    v3()
    
    def task(arg):def inner():print(arg)return innerinner_func_list = []
    for val in [11,22,33]:inner_func_list.append( task(val) )inner_func_list[0]() # 11
    inner_func_list[1]() # 22
    inner_func_list[2]() # 33
    
    """ 基于多线程去下载视频 """
    from concurrent.futures.thread import ThreadPoolExecutorimport requestsdef 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.contentdef 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_filePOOL = 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()
    

    在这里插入图片描述

3.装饰器

现在给你一个函数,在不修改函数源码的前提下,实现在函数执行前和执行后分别输入 “before” 和 “after”。

def func():print("我是func函数")value = (11,22,33,44) return valueresult = func()
print(result)

3.1 第一回合

你的实现思路:

def func():print("before")print("我是func函数")value = (11,22,33,44) print("after")return valueresult = func()

我的实现思路:

def func():print("我是func函数")value = (11, 22, 33, 44)return valuedef outer(origin):def inner():print('inner')origin()print("after")return innerfunc = outer(func)
result = func()

处理返回值:

def func():print("我是func函数")value = (11, 22, 33, 44)return valuedef outer(origin):def inner():print('inner')res = origin()print("after")return resreturn innerfunc = outer(func)
result = func()

3.2 第二回合

在Python中有个一个特殊的语法糖:

def outer(origin):def inner():print('inner')res = origin()print("after")return resreturn inner@outer
def func():print("我是func函数")value = (11, 22, 33, 44)return valuefunc()

3.3 第三回合

请在这3个函数执行前和执行后分别输入 “before” 和 “after”

def func1():print("我是func1函数")value = (11, 22, 33, 44)return valuedef func2():print("我是func2函数")value = (11, 22, 33, 44)return valuedef func3():print("我是func3函数")value = (11, 22, 33, 44)return valuefunc1()
func2()
func3()

你的实现思路:

def func1():print('before')print("我是func1函数")value = (11, 22, 33, 44)print("after")return valuedef func2():print('before')print("我是func2函数")value = (11, 22, 33, 44)print("after")return valuedef func3():print('before')print("我是func3函数")value = (11, 22, 33, 44)print("after")return valuefunc1()
func2()
func3()

我的实现思路:

def outer(origin):def inner():print("before 110")res = origin()  # 调用原来的func函数print("after")return resreturn inner@outer
def func1():print("我是func1函数")value = (11, 22, 33, 44)return value@outer
def func2():print("我是func2函数")value = (11, 22, 33, 44)return value@outer
def func3():print("我是func3函数")value = (11, 22, 33, 44)return valuefunc1()
func2()
func3()

装饰器,在不修改原函数内容的前提下,通过@函数可以实现在函数前后自定义执行一些功能(批量操作会更有意义)。

优化

优化以支持多个参数的情况。

def outer(origin):def inner(*args, **kwargs):print("before 110")res = origin(*args, **kwargs)  # 调用原来的func函数print("after")return resreturn inner@outer  # func1 = outer(func1)
def func1(a1):print("我是func1函数")value = (11, 22, 33, 44)return value@outer  # func2 = outer(func2)
def func2(a1, a2):print("我是func2函数")value = (11, 22, 33, 44)return value@outer  # func3 = outer(func3)
def func3(a1):print("我是func3函数")value = (11, 22, 33, 44)return valuefunc1(1)
func2(11, a2=22)
func3(999)

其中,我的那种写法就称为装饰器。

  • 实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数。

  • 实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能。

  • 适用场景:多个函数系统统一在 执行前后自定义一些功能。

  • 装饰器示例

    def outer(origin):def inner(*args, **kwargs):# 执行前res = origin(*args, **kwargs)  # 调用原来的func函数# 执行后return resreturn inner@outer
    def func():passfunc()
    

伪应用场景

在以后编写一个网站时,如果项目共有100个页面,其中99个是需要登录成功之后才有权限访问,就可以基于装饰器来实现。

pip3 install flask

基于第三方模块Flask(框架)快速写一个网站:

from flask import Flaskapp = Flask(__name__)def index():return "首页"def info():return "用户中心"def order():return "订单中心"def login():return "登录页面"app.add_url_rule("/index/", view_func=index)
app.add_url_rule("/info/", view_func=info)
app.add_url_rule("/login/", view_func=login)app.run()

基于装饰器实现的伪代码:

from flask import Flaskapp = Flask(__name__)def auth(func):def inner(*args, **kwargs):# 在此处,判断如果用户是否已经登录,已登录则继续往下,未登录则自动跳转到登录页面。return func(*args, **kwargs)return inner@auth
def index():return "首页"@auth
def info():return "用户中心"@auth
def order():return "订单中心"def login():return "登录页面"app.add_url_rule("/index/", view_func=index, endpoint='index')
app.add_url_rule("/info/", view_func=info, endpoint='info')
app.add_url_rule("/order/", view_func=order, endpoint='order')
app.add_url_rule("/login/", view_func=login, endpoint='login')app.run()

重要补充:functools

你会发现装饰器实际上就是将原函数更改为其他的函数,然后再此函数中再去调用原函数。

def handler():passhandler()
print(handler.__name__) # handler
def auth(func):def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth
def handler():passhandler()
print(handler.__name__) # inner
import functoolsdef auth(func):@functools.wraps(func)def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth
def handler():passhandler()
print(handler.__name__)  # handler

其实,一般情况下大家不用functools也可以实现装饰器的基本功能,但后期在项目开发时,不加functools会出错(内部会读取__name__,且__name__重名的话就报错),所以在此大家就要规范起来自己的写法。

import functoolsdef auth(func):@functools.wraps(func)def inner(*args, **kwargs):"""巴巴里吧"""res = func(*args, **kwargs)  # 执行原函数return resreturn inner

总结

  1. 函数可以定义在全局、也可以定义另外一个函数中(函数的嵌套)

  2. 学会分析函数执行的步骤(内存中作用域的管理)

  3. 闭包,基于函数的嵌套,可以将数据封装到一个包中,以后再去调用。

  4. 装饰器

    • 实现原理:基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数。

    • 实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能。

    • 适用场景:多个函数系统统一在 执行前后自定义一些功能。

    • 装饰器示例

      import functoolsdef auth(func):@functools.wraps(func)def inner(*args, **kwargs):"""巴巴里吧"""res = func(*args, **kwargs)  # 执行原函数return resreturn inner
      

作业

  1. 请为以下所有函数编写一个装饰器,添加上装饰器后可以实现:执行func时,先执行func函数内部代码,再输出 “after”

    def func(a1):return a1 + "傻叉"def base(a1,a2):return a1 + a2 + '傻缺'def foo(a1,a2,a3,a4):return a1 + a2 + a3 + a4 + '傻蛋'
    
  2. 请为以下所有函数编写一个装饰器,添加上装饰器后可以实现:将被装饰的函数执行5次,讲每次执行函数的结果按照顺序放到列表中,最终返回列表。

    import random def func():return random.randint(1,4)result = func() # 内部自动执行5次,并将每次执行的结果追加到列表最终返回给result
    print(result) 
    
  3. 请为以下函数编写一个装饰器,添加上装饰器后可以实现: 检查文件所在路径(文件件)是否存在,如果不存在自动创建文件夹(保证写入文件不报错)。

    def write_user_info(path):file_obj = open(path, mode='w', encoding='utf-8')file_obj.write("武沛齐")file_obj.close()write_user_info('/usr/bin/xxx/xxx.png')
    
  4. 分析代码写结果:

    def get_data():scores = []def inner(val):scores.append(val)print(scores)return innerfunc = get_data()func(10)
    func(20)
    func(30)
    
  5. 看代码写结果

    name = "武沛齐"def foo():print(name)def func():name = "root"foo()func()
    
  6. 看代码写结果

    name = "武沛齐"def func():name = "root"def foo():print(name)foo()func()
    
  7. 看代码写结果

    def func(val):def inner(a1, a2):return a1 + a2 + valreturn innerdata_list = []for i in range(10):data_list.append(  func(i)   )print(data_list)
    
  8. 看代码写结果

    def func(val):def inner(a1, a2):return a1 + a2 + valreturn innerdata_list = []for i in range(10):data_list.append(func(i))v1 = data_list[0](11,22)
    v2 = data_list[2](33,11)print(v1)
    print(v2)
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/658757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广告营销为什么需要使用代理IP

在广告营销中使用代理IP有几个主要原因 绕过限制和封禁 某些广告平台或网站可能会限制或封禁特定IP地址或IP地址范围,以防止滥用或欺诈行为。使用代理IP可以帮助您绕过这些限制,使您能够在被封禁的IP范围之外进行广告投放。 地理定位和目标市场 广告…

知识点积累系列(六)操作系统(Linux+Windows+MacOS)篇【持续更新】

云原生学习路线导航页(持续更新中) 本文是 知识点积累 系列文章的第六篇,记录日常学习中遇到的 操作系统相关 的知识点,包括 Linux、Windows、MacOS等 1.Linux相关 1.1.shell脚本 1.2.命令相关 1.2.1.vim命令 1.2.2.nslookup命…

GPT-4 Vision调试任何应用,即使缺少文本日志 升级Streamlit七

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

本地配置Joplin Server用于Joplin笔记同步并实现公网远程访问

文章目录 1. 安装Docker2. 自建Joplin服务器3. 搭建Joplin Sever4. 安装cpolar内网穿透5. 创建远程连接的固定公网地址 Joplin 是一个开源的笔记工具,拥有 Windows/macOS/Linux/iOS/Android/Terminal 版本的客户端。多端同步功能是笔记工具最重要的功能,…

LabVIEW潜油电泵数据采集系统

LabVIEW潜油电泵数据采集系统 介绍一个基于LabVIEW的潜油电泵数据采集系统。该系统目的是通过高效的数据采集和处理,提高潜油电泵的性能监控和故障诊断能力。 系统由硬件和软件两部分组成。硬件部分主要包括数据采集卡、传感器和电泵等,而软件部分则是…

IMX6LL|打造自己的驱动总线

xbus:打造自属的驱动总线 驱动总线 软件与硬件代码分离,提高程序的复用性 device–关联硬件代码driver_devices–关联软件代码bus_type–统一管理、设置match匹配规则 设备驱动模型体现分离思想 bus-xbus-devices-drivers 总线管理 buses_init()函…

鸿蒙系统扫盲(七):勘误补充总结,收个尾

这是笔者鸿蒙扫盲系列的最后一篇了,准备对过去的六篇扫盲系列文章,错误的地方做一些勘误,并且补充更新一些朋友们感兴趣的知识,最后收个尾。 1.勘误,编译型语言和解释型语言 在鸿蒙系统扫盲(五&#xff0…

网工内推 | 网络安全工程师专场,大平台,六险一金

01 汽车之家 招聘岗位:高级网络安全工程师 职责描述: 1、负责公司网站、系统与产品的漏洞扫描、渗透测试与安全评估工作; 2、负责公司安全系统与安全设备的运维,负责公司网络安全监控管理; 3、负责公司安全事件的应急…

社区投稿|Desig质押聚合器功能,帮助用户选出更适合的质押策略

在Sui上,不同的质押协议提供收益各异的产品,因此用户面临着众多可以质押token的协议,眼花缭乱无从选择。Desig质押聚合器功能现已整合到Desig钱包扩展中,极大地简化了寻找质押策略的流程。事实上,其智能质押功能支持完…

记录:Windows上QML程序打包

0.本文修改记录 (2019-9-3) 修改了VC环境相关的内容 (2020-3-5) 修改了QML模块相关的内容 (2022-8-31)one-rabbit大佬指出打包命令的参数错误,根据文档可知:qmldir应该为exe对应项…

transformer_位置编码代码笔记

transformer_位置编码代码笔记 transformer输入的序列中,不同位置的相同词汇可能会表达不同的含义,通过考虑位置信息的不同来区分序列中不同位置的相同词汇。 位置编码有多种方式,此处仅记录正余弦位置编码 正余弦位置编码公式如下&#x…

宠物用品/宠物自动饮水机方案

宠物自动饮水机方案原理 宠物自动饮水机,也叫做智能宠物饮水机,是一种为宠物设计的智能化饮水器。应用核心主要在于智能化水泵控制,以及外围传感器电路。 宠物自动饮水机使用方便,不用频繁的换水。另外,自来水的水质可…

(6)Elastix图像配准:可视化配准工具

文章目录 前言一、配准工具1.1、基于Elastix的可视化配准工具1.1.1、elastix-napari:基于napari的Elastix图像配准1.1.2、SlicerElastix:基于3D slice的Elastix图像配准1.1.3、BIRDS:基于ImageJ的Elastix双通道图像配准 1.2、基于ITK开发的配…

微信小程序如何实现点击上传图片功能

如下所示,实际需求中常常存在需要点击上传图片的功能,上传前显示边框表面图片显示大小,上传后将图形缩放到边框大小。 实现如下: .wxml <view class="{{img_src==?blank-area:}}" style="width:100%;height:40%;display:flex;align-items: center;jus…

容器算法迭代器初识

#include<iostream> using namespace std; #include<vector> //vetor容器存放内置数据类型 void test01() {//创建了一个vector容器&#xff0c;数组 vector<int> v;//向容器中插入数据v.push_back (10);//尾插 v.push_back (20);v.push_back (30);v.push_ba…

WIN11 - WSL(Windows Subsystem for Linux) 安装教程

前言 WSL&#xff0c;即Windows Subsystem for Linux&#xff0c;是一种在Windows操作系统上运行Linux二进制文件的兼容层。该层提供了Linux环境和GNU工具&#xff0c;可以在Windows系统上运行Linux应用程序。WSL使得开发人员可以在Windows系统上使用Linux工具和命令行界面&am…

项目实战:一个基于标准库的具备最值获取的万能容器实现

目录 写在前面 需求 分析 接口设计 项目实现 一些思考与总结 致谢 写在前面 刚刚介绍了变参模板和完美转发&#xff0c;现在换一换脑子做一个小的项目实战吧。博主最近学习的是标准库&#xff0c;总体来说&#xff0c;我认为标准库中的内容是很trivial的&#xff0c;重点…

04 避免 Latch 的产生

Latch 是什么 latch 即锁存器&#xff0c;是一种对电平敏感的存储单元电路&#xff0c;和寄存器一样都是基本存储单元&#xff0c;但是寄存器是边沿触发的存储器&#xff0c;锁存器是电平触发的存储器。 组合逻辑电路和时序逻辑电路 在数字电路中将逻辑电路分成两大类&#…

Java学习笔记(十一)——常用类

一、包装类 &#xff08;一&#xff09;包装类和基本数据类型的转换 ​编辑 &#xff08;二&#xff09;包装类型和String类型的相互转换 &#xff08;三&#xff09;Integer类和Character类的常用方法 二、String &#xff08;一&#xff09;创建String对象的两种方式 …

【爬虫专区】批量下载PDF (无反爬)

天命:只要没反爬,一切都简单 这次爬取的是绿盟的威胁情报的PDF 先看一下结构,很明显就是一个for循环渲染 burp抓包会发现第二次接口请求 接口请求一次就能获取到了所有的数据 然后一个循环批量下载数据即可,其实没啥难度的 import requests,osres = requests.get("…