深入理解 python 虚拟机:生成器停止背后的魔法

理解 Python 虚拟机:进程、线程和协程 现在假如需要处理很多网络请求,一个线程处理一个请求,当处理一个请求的时候我们需要等待客户端的响应,线程在等待客户端响应的时候是处于阻塞状态不需要使用 CPU,假设 CPU 的使用率为 0.0001%,那么我们大概需要 1000000 个线程才能够将 CPU 的使用率达到 100%,而通常我们在内核创建一个线程大概需要 2MB 的内存,4GB 内存大概能够创建 2048 个线程,这远远达不到我们需要创建的线程个数。Python 当中的线程和我们常说的线程是一致的吗? 阅读详情

深入理解 python 虚拟机:生成器停止背后的魔法

在本篇文章当中主要给大家介绍 Python 当中生成器的实现原理,尤其是生成器是如何能够被停止执行,而且还能够被恢复的,这是一个非常让人疑惑的地方。因为这与我们通常使用的函数的直觉是相违背的,函数之后执行完成之后才会返回,而生成表面是函数的形式,但是这违背了我们正常的编程直觉。

深入理解生成器与函数的区别

为了从根本上建立对生成器的认识,我们首先就需要深入理解一下生成器和函数的区别。其实在从虚拟机的层面来看,他们两个都是对象,只不过一个是生成器对象,一个是函数对象。在 Python 当中,如果你在函数里面使用了 yield 语句,那么你的这个函数在被调用的时候就不会被执行,而是会返回一个生成器对象。

>>> def bar():
...     print("before yield")
...     res = yield 1
...     print(f"{res = }")
...     print("after yield")
...     return "Return Value"
...
>>> generator = bar()
>>> generator
<generator object bar at 0x105267510>
>>> bar
<function bar at 0x10562fc40>
>>>

在 Python 当中有的对象是可以直接调用的,比如你自己的类如果实现了__call__方法的话,这个类生成的对象就是一个可调用对象,在 Python 当中一个最常见的可调用对象就是函数了,生成器和函数的区别之一就是,生成器不能够直接被调用,而函数可以。

>>> generator()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'generator' object is not callable
>>>

在上面的代码当中我们要明确 bar 是一个函数,但是这个函数和正常的函数有一点区别,这个函数在被调用的时候不会直接执行代码,而是会返回一个生成器对象,因为在这个函数体当中使用了 yield 语句,我们称这种函数为生成器函数 (generator function),在 Python 当中你可以通过查看一个函数的 co_flags 字段查看一个函数的属性,如果这个字段和 0x0020 进行 & 操作之后的结果大于 0,那么就说明这个函数是一个生成器函数。

>>> (bar.__code__.co_flags & 0x0020) > 0
True
>>> bar.__code__.co_flags & 0x0020
32

从上面的代码当中我们可以看到 bar 就是一个生成器函数,除了上面的方法 Python 的标准库也提供了方法去辅助我们进行判断。

>>> import inspect
>>> inspect.isgeneratorfunction(bar)
True

上面的特性在 Python 程序进行编译的时候,编译器可以做到这一点,当发现一个函数当中存在类似 yield 的语句的时候就在函数的 co_flags 字段当中和 0x0020 进行或操作,然后将这个值保存在 co_flags 当中。

总之生成器和函数之间的关系为:生成器对象是通过调用生成器函数得到的,调用生成器函数的返回对象是生成器。

虚实交错的时空魔法

首先我们需要了解的是,如果我们想让一个生成器对象执行下去的话,我们可以使用 next 或者 send 函数,进行实现:

>>> next(generator)
before yield
1
>>> next(generator)
res = None
after yield
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: Return Value

在 CPython 实现的虚拟机当中,如果我们想要正确的使用 send 函数首先需要让生成器对象执行到第一个 yield 语句,我们可以使用 next(generator) 或者 generator.send(None)。比如在上面的第一条语句当中执行 next(generator),运行到语句 res = yield 1,但是这条语句还没有执行完,需要我们调用 send 函数之后才能够完成赋值操作,send 函数的参数会被赋值给变量 res 。当整个函数体执行完成之后虚拟机就会抛出 StopIteration 异常,并且将返回值保存到 StopIteration 异常对象当中:

>>> generator = bar()
>>> next(generator)
before yield
1
>>> try:
...     generator.send("None")
... except StopIteration as e:
...     print(f"{e.value = }")
...
res = 'None'
after yield
e.value = 'Return Value'
>>>

上面的代码当中可以看到,我们正确的执行力我们在上面谈到的生成器的使用方法,并且将生成器执行完成之后的返回值保存到异常的 value 当中。

生成器内部实现原理

从上面的关于生成器的使用方式来看,生成器可以在函数执行到一半的时候停止,然后继续恢复执行,为了实现这一点我们就需要有一种手段去保存函数执行的状态。但是我们需要保存函数执行的那些状态呢?最重要的两点就是代码现在执行到什么位置了,因为我们之后要继续从下一条指令开始恢复执行,同时我们需要保存虚拟机的栈空间,就是在执行字节码的时候使用到的 valuestack,注意这不是栈帧,同时还有执行函数的局部变量表,这里主要是保存一些局部变量的。而这些东西都保存在虚拟机的栈帧当中了,这一点我们在前面的文章当中已经详细介绍过了。

因此根据这些分析我们应该知道了,生成器里面最重要的就是一个虚拟机的栈帧数据结构了。一个生成器对象当中一定需要有一个虚拟机的栈帧,在 CPython 的实现当中,生成器对象的数据结构如下:

typedef struct
{
    /* The gi_ prefix is intended to remind of generator-iterator. */
    PyObject ob_base;
    struct _frame *gi_frame;
    char gi_running;
    PyObject *gi_code;
    PyObject *gi_weakreflist;
    PyObject *gi_name;
    PyObject *gi_qualname;
    _PyErr_StackItem gi_exc_state;
} PyGenObject;

  • gi_frame: 这个字段就是表示生成器所拥有的栈帧。
  • gi_running: 表示生成器是否在运行。
  • gi_code: 表示对应生成器函数的代码(字节码)。
  • gi_weakreflist: 用于保存这个栈帧对象保存的弱引用对象。
  • gi_name 和 gi_qualname 都是表示生成器的名字,后者更加详细。
  • gi_exc_state: 用于保存执行生成器代码之前的程序状态,因为之前的代码可能已经产生一些异常了,这个主要用于保存之前的程序状态,待生成器返回之后就进行恢复。
class A:
	def hello(self):
		yield 1

if __name__ == '__main__':
	g = A().hello()
	print(g.__name__)
	print(g.__qualname__)

上面的程序输出结果为:

hello
A.hello

生成器对应的字节码行为

我们通过下面的例子来分析一下,生成器 yield 对应的字节码:

>>> import dis
>>> def hello():
...     yield 1
...     yield 2
...
>>> dis.dis(hello)
  2           0 LOAD_CONST               1 (1)
              2 YIELD_VALUE
              4 POP_TOP

  3           6 LOAD_CONST               2 (2)
              8 YIELD_VALUE
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE

在上面的程序当中只有和生成器相关的字节码为 YIELD_VALUE,在加载完常量 1 之后就会执行 YIELD_VALUE 指令,虚拟机在执行完 yield 指令之后,就会直接返回,此时虚拟机的状态——valuestack 和当前指令执行的位置(在上面的这个例子当中就是 4)都会被保存到虚拟机栈帧当中,当下一次执行生成器的代码的时候就会直接从 POP_TOP 指令直接执行。

我们再来看一下另外一个比较重要的指令 YIELD_FROM:

>>> def generator_b(gen):
...     yield from gen
...
>>> dis.dis(generator_b)
  2           0 LOAD_FAST                0 (gen)
              2 GET_YIELD_FROM_ITER
              4 LOAD_CONST               0 (None)
              6 YIELD_FROM
              8 POP_TOP
             10 LOAD_CONST               0 (None)
             12 RETURN_VALUE

我们现在用一个简单的例子重新回顾一下程序的行为:

def generator_a():
	yield 1
	yield 2

def generator_b(gen):
	yield from gen

if __name__ == '__main__':
	gen = generator_b(generator_a())
	print(gen.send(None))
	print(gen.send(None))
	try:
		gen.send(None)
	except StopIteration:
		print("generator exit")

上面的程序输出结果如下所示:

1
2
generator exit

从上面程序的输出结果我们可以看到 generator_a 的两个值都会被返回,这些魔法隐藏在字节码 YIELD_FROM 当中。YIELD_FROM 字节码会调用栈顶上的生成器对象的 send 方法,并且将参数生成器对象 gen 的返回结果返回,比如 1 和 2 这两个值会被返回到 generator_b ,然后 generator_b 会将这个结果继续传播出来。

  • 在这个字节码执行最后会进行判断虚拟机当中是否出现了 StopIteration 异常,如果出现了则说 yield from 的生成器已经执行完了,则 generator_b 继续往下执行。
  • 如果没有 StopIteration 异常,则说明 yield from 的生成器没有执行完成,这个时候虚拟机会将当前栈帧的字节码执行位置往前移动,这么做的目的是让下一次生成器执行的时候继续执行 YIELD_FROM 字节码,这就是 YIELD_FROM 能够将另一个生成器对象执行完整的秘密。

总结

在本篇文章当中主要分析的生成器内部实现原理和相关的两个重要的字节码,分析了生成器能够停下来还能够恢复执行的原因。本文最重要的两点就是区分函数和生成器和 YIELD 、YIELD_FROM 两个字节码,生成器是生成器函数返回的对象,YIELD 会直接进行函数返回,虚拟机不会继续往下执行,YIELD_FROM 除了会进行函数返回还会将字节码的执行位置往前移动,以保证 YIELD_FROM 下一次还能够被执行。


本篇文章是深入理解 python 虚拟机系列文章之一,文章地址:github.com/Chang-LeHun…

更多精彩内容合集可访问项目:github.com/Chang-LeHun…

关注公众号:一无是处的研究僧,了解更多计算机(Java、Python、计算机系统基础、算法与数据结构)知识。

---------------------------END---------------------------

题外话

当下这个大数据时代不掌握一门编程语言怎么跟的上脚本呢?当下最火的编程语言Python前景一片光明!如果你也想跟上时代提升自己那么请看一下.

在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。


👉优快云大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述
👉 优快云大礼包:gift::[全网最全《Python学习资料》免费赠送:free:!](https://blog.youkuaiyun.com/weixin_68789096/article/details/132275547?spm=1001.2014.3001.5502) (安全链接,放心点击)

若有侵权,请联系删除

从RSA原理到实战:深入理解Beyond Compare 5密钥生成与软件授权机制 RSA非对称加密算法是现代软件授权保护的核心技术之一,其原理基于大数分解的数学难题,通过公钥与私钥的配对实现数据加密和签名验证。在软件工程实践中,该算法常被用于验证许可证的合法性,确保只有经过授权的用户才能使用软件的全部功能。理解RSA在软件保护中的应用,有助于开发者构建更安全的授权系统,也便于技术爱好者分析软件的激活机制。本文聚焦于Beyond Compare 5这款经典文件对比工具,通过逆向工程分析其内置的RSA公钥验证流程,并探讨如何通过修改关键数据或生成匹配密钥来实现特定场景下的功能测试。文中涉及的 阅读详情

相关推荐

从虚拟机到编译器:Nand2Tetris项目实践指南

理解计算机系统如何运行高级语言程序,需要掌握从高级语言到机器指令的完整转换链条。这一过程的核心原理在于软件抽象的分层架构:高级语言通过编译器转换为中间表示(如虚拟机指令),再由虚拟机翻译器生成目标平台的汇编代码,最终由汇编器生成可执行的机器码。这种分层设计极大地提升了软件的可移植性和开发效率,是构建现代操作系统和复杂应用的基础技术。在Nand2Tetris项目的实践中,你将亲手实现虚拟机翻译器和编译器这两个关键组件,完成从逻辑门到可运行俄罗斯方块游戏的完整软件栈构建。通过实现栈式虚拟机指令集和Jack语言的

weixin_34023982的博客 415

TypeError: ‘generator‘ object is not subscriptable

问题分析:‘generator’对象没有下标,数组可以有下标。 import os print(os.walk(r'C:\Users\user\Desktop\Test')[0]) 解决方法:可以把下标去掉,然后再用for循环依次取出数据。 import os for root,dirs,files in os.walk(r'C:\Users\user\Desktop\Test'): print(dirs) ...

ChenWenKen的博客 1277

Python暴力破解MD5哈希:从原理到工程优化的完整指南

哈希算法是信息安全领域的基石,它将任意长度的数据映射为固定长度的唯一指纹,确保数据的完整性与不可篡改性。MD5作为一种经典的哈希函数,因其快速计算和固定输出特性,曾广泛应用于密码存储和文件校验。然而,其已被证明存在碰撞漏洞,安全性不足,但理解其破解原理对认识密码学攻防至关重要。暴力破解的核心原理是通过穷举搜索,在巨大的明文空间中寻找与目标哈希值匹配的原始输入,这本质上是一个计算密集型的搜索优化问题。通过Python实现,可以深入实践算法优化与高性能计算,例如利用多进程并行计算来压榨CPU性能,或采用字典攻击

weixin_33938733的博客 357

TypeError: ‘generator‘ object is not callable

在fetch的时候不知道为什么发生了故障,后来我发现我的数据不符合相应的条件。所以直接把如图所示的地方注释掉了。

zhongruizhe的博客 1118

Python异步HTTP压力测试工具开发:从原理到实战

网络压力测试是评估Web服务、API接口及网络设备性能的关键技术手段,其核心原理在于模拟高并发用户请求,以探测系统在极限负载下的响应能力、资源消耗及稳定性瓶颈。在技术实现层面,异步IO(asyncio)因其在单线程内通过事件循环调度协程的高效模型,成为处理海量并发I/O操作的首选方案,它能以极少的系统资源支撑数万并发连接,特别适用于构建定制化的压力测试工具。结合aiohttp库,开发者可以快速构建高性能的HTTP客户端,实现请求流量控制、结果统计与实时监控。这类工具在安全研究、教学演示及授权测试环境中具有重

weixin_34111790的博客 471

Kali Linux 2026 从零入门:一周掌握渗透测试核心工具与实战

渗透测试是网络安全领域的核心实践,旨在通过模拟攻击来评估系统防御的有效性。其原理在于主动发现并利用系统、网络或应用中的安全弱点,从而验证安全策略的完备性。掌握渗透测试技术对于构建主动防御体系、提升整体安全水位具有关键价值,广泛应用于企业安全评估、合规审计及安全研究等场景。Kali Linux作为专为渗透测试设计的Linux发行版,集成了Nmap、Metasploit等数百种专业工具,是安全从业者进行信息收集、漏洞利用和Web应用测试的标准化平台。本文聚焦于Kali Linux的快速上手,详细解析了通过虚拟机

weixin_34348805的博客 351

小白入门常见错误python:TypeError: ‘generator‘ object is not subscriptable (萌新踩雷!!!)

小白入门常见、易错类型python:TypeError: ‘generator’ object is not subscriptable 的解决方法(萌新踩雷!!!) 话不多说,上代码: 报错:TypeError: ‘generator’ object is not subscriptable 的解决方法 报错截图: 源代码截图: 源代码: #Tools: Pycharm 2017.3.2 _author_ = ' Hermione' m,n=map(int,input().split()) a=[]

HarryOtter的博客 1万+

技术博客人格化构建:从.NET实践看开发者内容生产方法论

技术博客本质上是开发者认知传播的载体,其核心在于将抽象技术还原为真实问题解决过程。理解‘技术传播的认知断层’与‘开发者决策链’是提升内容价值的前提——当读者面临SignalR选型、EF Core性能瓶颈或Blazor Session超时等典型场景时,他们需要的不是API文档复述,而是可验证的工程判断依据和可复用的调试路径。人格化并非风格修饰,而是通过身份真实性、成长可见性、失败透明度与价值一致性四维支撑,建立技术信任;而‘人→技术人→程序员’的三阶跃迁,则确保内容既降低新手认知负荷,又满足资深工程师对底层机

diedangxiang4092的博客 558

【错】'generator' object is not subscriptable

python3.6在读取excel中特定列的时候一直报错 后来经过多方查询,终于找到原因了,return sheet.rows[rowNo - 1] 因为sheet.rows是生成器类型,不能使用索引,所以需要转换成list之后再使用索引,list(sheet.rows)[2]这样就获取到第二行的tuple对象。正确的写法是: 希望可以给到你帮助 ...

Marry_Ma的博客 1万+

网格自适应_Comsol案例解析17:自适应网格的使用

本期导读自适应网格细化有许多优势,比如可以不用对网格进行全局加密,增加计算精度,又会降低求解自由度。本期仍然以气泡上升案例为例,在两相流模块中使用自适应网格。【打开案例模型】【修改网格】适当让气泡边界加密,注意,曲率因子越小,曲线上的网格越密【添加自适应网格】使用默认的参数即可,这里的误差指示器用的是水平集phi。可以根据具体求解模型选择适当的自变量作为误差指示器。【口诀】默认的一般是最...

weixin_28726871的博客 5681

在mac OS下安装SQL Developer

最近一直在折腾Oracle数据库,但由于电脑是mac系统,plsql developer用不了,远程管理一直不是很方便。后来听说Navicat不错,就也装了个试试看,发现界面看起来确实不错。今天心血来潮,想试试oracle自己开发的client。用惯plsql developer的人也可以来试试看,毕竟是自己人开发的,兼容性应该会不错吧。下面就把安装过程分享给新手或者需要帮助的朋友。 1.

bonbonboo的专栏 2万+

openpyxl中遇到TypeError: ‘generator‘ object is not subscriptable的问题和解决方案

openpyxl中遇到TypeError: 'generator' object is not subscriptable的问题和解决方案

qq_38472574的博客 482

Kettle下载与安装教程【保姆版】

Kettle简介 Kettle最早是一个开源的ETL工具,全称为KDE Extraction, Transportation, Transformation and Loading Environment。后来Kettle重命名为Pentaho Data Integration 。 它由Java开发,支持跨平台运行,其特性包括:支持100%无编码、拖拽方式开发ETL数据管道;可对接包括传统数据库、文件、大数据平台、接口、流数据等数据源;支持ETL数据管道加入机器学习算法。 主要功能 Pentaho D

weixin_43407520的博客 12万+

深入理解 Python 虚拟机:协程初探——不过是生成器而已

在 Python 3.4 Python 引入了一个非常有用的特性——协程,在本篇文章当中我们将详细介绍一下 Python 协程的原理以及虚拟机具体的实现协程的方式。

qq_45537774的博客 543

SAP FIORI静态磁贴从零到一:配置实战与权限打通

本文详细介绍了SAP FIORI静态磁贴的配置流程与权限管理,从准备工作到后台配置、目标映射、前台组织及权限分配,提供了实战技巧与常见问题解决方案。重点解析了静态磁贴的创建、目标映射配置及权限打通等关键步骤,帮助用户快速掌握FIORI静态磁贴的配置方法。

weixin_29266647的博客 248

【脑电分析系列】第7篇:频域分析基石 — 功率谱密度(PSD)的计算与常见方法对比

本文探讨了脑电图(EEG)频域分析的核心方法——功率谱密度(PSD)。通过对比基于快速傅里叶变换的周期图法和更稳健的Welch's方法,指出后者通过分段、加窗和平均处理,能有效降低估计方差,更适合分析非稳态的脑电信号。文章详细解析了关键参数设置对频率分辨率和统计稳定性的影响,并提供了Python计算实现。PSD分析将复杂的脑电信号转换为直观的频域特征,为研究认知功能和神经疾病提供重要依据。

qq_32516809的博客 1800

深入理解 Python 虚拟机:进程、线程和协程

在本篇文章当中我们将通过分析部分源代码来详细分析 Python 当中的进程、线程和协程,重点讨论线程的创建过程和协程是如何被使用的。

qq_45537774的博客 322

从零开始学习CANoe(三)—— 系统变量的创建和使用

从零开始学习CANoe(三)—— 系统变量的创建和使用

蚂蚁小兵 1万+

利用CPU散热系统生成动态白噪音:Python实现硬件交互与音频合成

白噪音与粉红噪音作为常见的环境声,在提升专注力与掩蔽干扰噪音方面具有显著效果,其原理在于通过均匀的频谱分布覆盖人耳敏感频段。从技术实现角度看,这涉及数字信号处理与音频合成技术,通常通过算法生成随机信号并滤波处理。在工程实践中,此类技术可与系统监控结合,创造动态交互体验。例如,通过Python的psutil库获取CPU温度与使用率等系统状态数据,利用numpy和sounddevice库实时生成对应频谱特性的音频,实现硬件传感器数据到可听化反馈的映射。这种**系统监控**与**音频合成**的联动,不仅深化了对计

weixin_30654583的博客 403

【Proteus仿真】AT89C51单片机中断系列仿真——INT0中断控制LED小灯/INT0和INT1中断控制数码管

本文介绍了基于51单片机外部中断(INT0/INT1)的四个实践案例:1)INT0控制LED开关;2)INT0中断实现数码管计数/清零;3)INT0中断构建秒表功能(启动/暂停/清零);4)INT0/INT1双中断独立控制两组数码管计数。每个案例包含电路原理图、接线说明及完整源代码,重点演示了外部中断在硬件控制中的应用方法。附加硬件工程师笔试面试资料链接,涵盖器件知识、Multisim教程等内容,适合嵌入式学习者参考实践。(149字)

XU157303764的博客 1911

AI应用架构师实战:半导体器件仿真AI智能体系统搭建

半导体器件仿真(如MOSFET、FinFET等)是芯片设计的核心环节,传统流程依赖专家手动调参、多物理场仿真引擎(如TCAD)耗时(小时级至天级)、经验难以沉淀,导致研发周期长、成本高。如何构建一个AI智能体系统,实现仿真任务的自动化调度、参数智能优化、结果分析与知识沉淀,成为提升半导体研发效率的关键挑战。

移动开发前沿的博客 1222

python3 核心笔记

本文主要是针对python3的一些核心要点做一些记录,感兴趣的可以关注和订阅。会持续更新,这个玩意学习一下,可以为数据分析和AI打下一定的基础。

yanghuashuiyue的专栏 617

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

网络安全零基础入门:从构建者思维到工程实践的系统路径

网络安全的核心在于理解系统如何工作与防御,而非简单的攻击技巧。从基础概念入手,理解计算机系统、网络协议(如TCP/IP、HTTP/HTTPS)和数据库(SQL)的工作原理,是构建安全能力的基石。掌握虚拟化技术搭建安全实验环境,熟练使用命令行与版本控制工具(如Git),是工程实践的起点。Python作为自动化脚本语言,能高效处理日志分析、网络请求等任务,而Wireshark、Nmap等工具则延伸了分析网络流量与系统状态的能力。通过CTF挑战和模拟靶场实践,可以将理论应用于真实场景,培养系统性分析与问题定位的工

weixin_34117211的博客 418

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

VC++6.0与MFC框架:深入理解Windows桌面开发的核心机制与现代价值

消息驱动机制是Windows应用程序的基础架构,它定义了操作系统与应用程序之间通过消息队列进行通信的原理。这种机制确保了用户输入、系统事件和应用程序响应之间的高效协同,是理解GUI框架设计哲学的关键。在技术价值层面,消息驱动模型实现了界面与逻辑的解耦,为复杂交互提供了清晰的程序结构。应用场景广泛覆盖了从传统桌面软件到现代图形界面的各类程序。文档/视图架构作为数据与显示分离的经典设计模式,进一步提升了应用程序的可维护性和扩展性。Visual C++ 6.0及其MFC框架正是这些核心概念的早期完整实现,通过资源

weixin_33708432的博客 411

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

自建TOTP动态口令系统:从原理到实践,告别谷歌验证器依赖

双因素认证(2FA)是提升账户安全性的核心机制,其原理在于结合用户已知信息(密码)和用户持有物(动态令牌)进行双重验证。基于时间的一次性密码(TOTP)协议是实现2FA的主流技术标准,它通过共享密钥与时间戳的哈希运算,生成短暂有效的动态口令,在安全性与用户体验间取得了平衡。这项技术的价值在于为各类在线服务提供了开源、可互操作的强认证方案,广泛应用于GitHub、AWS等平台的登录保护以及企业内部系统访问控制。针对近期谷歌验证器等中心化工具可能存在的服务风险,本文将深入解析TOTP的**核心原理**与**密钥

cihongmo6452的博客 393
上一篇: 挑战自己,编程你的五子棋:Python+Pygame实践经验分享
下一篇: Python Fire:自动生成命令行接口
Python_P叔
博客等级 码龄3年 5446粉丝 827原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值