游乐游手机版
首页/前端开发/文章详情

Generator函数类型检测方法

时间:2026-07-03 06:59
判断一个函数是否为生成器函数,关键在于函数定义本身是否包含 yield 关键字,而非调用后返回的对象类型。最权威、最可靠的检测方式是使用 inspect isgeneratorfunction() —— 零副作用、100% 精准,甚至无需执行函数就能完成判断。 要判断一个函数是不是生成器函数,本质上
判断一个函数是否为生成器函数,关键在于函数定义本身是否包含 yield 关键字,而非调用后返回的对象类型。最权威、最可靠的检测方式是使用 inspect.isgeneratorfunction() —— 零副作用、100% 精准,甚至无需执行函数就能完成判断。

检测生成器函数(Generator Function)类型

要判断一个函数是不是生成器函数,本质上只需要看它定义时是否含有 yield 语句,而不是看它被调用后生成了什么结果。核心理念是:不能真的去执行这个函数。因此,最稳妥、最标准的方法就是使用 inspect.isgeneratorfunction()。下面来分析为什么其他常见做法行不通。

为什么不能用 isinstance(fn(), types.GeneratorType)

这种写法会实际调用函数,带来的后果往往不可控:

  • 可能触发副作用——修改全局变量、写入文件、发起网络请求,这些操作可能在检测时意外发生。
  • 可能耗尽资源——比如打开连接后未关闭,或生成临时文件句柄。
  • 可能直接抛出异常——参数校验失败、IO 错误,导致检测逻辑本身崩溃。

它检查的是“调用结果”而非“函数类型”,属于运行时判断,完全不适合静态类型识别的需求。

为什么不能靠 hasattr 或 __iter__ / __next__

这些属性只能说明对象是迭代器或可迭代对象,但无法区分下面几种情况:

  • 一个普通类自己实现了 __iter____next__,返回自定义迭代器
  • 一个返回 range(10) 的普通函数
  • 一个真正含有 yield 的生成器函数

三者都满足 hasattr(obj, '__iter__') and hasattr(obj, '__next__'),但只有第三种才是生成器函数。因此这种方法基本不可靠。

inspect.isgeneratorfunction() 才是唯一权威方案

该函数直接读取函数对象底层 code object 中的 co_flags 标志位(CO_GENERATOR)。这个标志在函数用 def 定义、编译器编译时就已经确定,无需调用函数,零副作用,100% 精准。具体来说:

  • 兼容 @staticmethod@classmethod、实例方法
  • 对普通函数、lambda、内置函数、functools.partial 等返回 False,不会误判
  • 标准库自带,无需第三方依赖,Python 3.2+ 全版本通用

实际使用示例

下面这段代码可以用在装饰器、插桩或测试框架中,统一处理生成器函数和普通函数:

import inspect

def safe_wrap(fn):
    if inspect.isgeneratorfunction(fn):
        def wrapped(*args, **kwargs):
            print(f"[GEN] Calling {fn.__name__}")
            yield from fn(*args, **kwargs)  # 保持生成器协议完整
        return wrapped
    else:
        def wrapped(*args, **kwargs):
            print(f"[FUNC] Calling {fn.__name__}")
            return fn(*args, **kwargs)
        return wrapped

这样包装后的函数,原生行为(比如 for 循环)完全保留,同时又统一了日志或监控逻辑。最关键的是——检测阶段根本不会执行原始函数,安全又可靠。

来源:https://www.php.cn/faq/2665623.html
上一篇JavaScript中Class作为模块导出的最佳实践完全指南与示例 下一篇Less与CSS原生变量冲突的转义处理技巧
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
JavaScript数组字面量与构造函数创建稀疏数组的差异
前端开发 · 2026-07-25

JavaScript数组字面量与构造函数创建稀疏数组的差异

数组字面量创建稠密数组,空位默认为undefined;Array()构造函数传入单个数字参数会生成稀疏数组,索引不存在且遍历方法跳过,多参数或非数字参数则行为与字面量一致。初始化稠密数组应使用Array from或fill。

如何优化Bootstrap按钮的焦点状态环CSS样式方法详解
前端开发 · 2026-07-25

如何优化Bootstrap按钮的焦点状态环CSS样式方法详解

Bootstrap按钮焦点样式优化需将内阴影改为外发光,覆盖所有焦点选择器避免原生蓝边闪烁。使用:focus-visible区分键盘与鼠标交互,同时处理按钮组圆角、父容器溢出及浏览器兼容性,确保焦点反馈清晰且符合无障碍标准。

Less中强制转换CSS单位适配不同移动端方案详解
前端开发 · 2026-07-25

Less中强制转换CSS单位适配不同移动端方案详解

Less单位转换需手动完成:用unit()剥离单位,通过变量控制基准值,再拼接目标单位。px2rem函数须区分输入类型(纯数字、带px单位等),基准值@base-font-size需全局定义且不可在媒体查询中重定义。所有运算发生在编译期,适配需提前编译多套CSS文件。

Vue 插件开发与使用完整指南
前端开发 · 2026-07-25

Vue 插件开发与使用完整指南

Vue插件通过install方法为应用注入全局属性、组件、指令、混入和provide等扩展能力,注册时机须在createApp之后、mount之前。插件支持对象或函数形式,使用app use()注册。开发时需注意命名冲突、配置默认值及错误处理,确保工程健壮性。

CSS响应式视频全屏黑边排版问题解决方案
前端开发 · 2026-07-25

CSS响应式视频全屏黑边排版问题解决方案

CSS响应式视频全屏黑边源于盒子模型、定位与加载策略缺失。需重置body边距及溢出,父容器用position:fixed与100dvh,video设为block+object-fit:cover。autoplay需加muted、playsinline。移动端用100dvh防地址栏抖动,低端机分辨率不超1倍。