如何准确判断一个对象是真正的 set 而不是 frozenset
技术百科
舞夢輝影
发布时间:2026-01-26
浏览: 次 最可靠的方式是用 type(obj) is set 或 type(obj) is frozenset 进行显式类型比对;isinstance(obj, set) 无法识别 frozenset 且易误判伪装类,hasattr(obj, 'add') 等接口检查更不可靠。
用 type() 直接比对最可靠
Python 中 set 和 frozenset 是两个独立类型,不能靠 isinstance(obj, set) 同时覆盖两者(因为 frozenset 不是 set 的子类),也不能只检查是否可变——有些自定义类也可能实现 add() 方法。最准确的方式是显式比对类型:
-
type(obj) is set→ 真正的set -
type(obj) is frozenset→ 真正的frozenset - 避免用
isinstance(obj, set):它对frozenset返回False,但对set返回True,看似可用,却掩盖了“非 set 却有 set 接口”的误判风险(比如某个类实现了add、remove但不是set)
hasattr(obj, 'add') 不能作为判断依据
很多教程建议用是否含 add 方法来区分,这是错的:
-
set有add,frozenset没有 → 表面看可行 - 但第三方类或用户自定义容器可能也定义了
add,却既不是set也不是frozenset - 更隐蔽的问题:
set的子类如果重写了__hash__变成不可变,它依然有add,但已不是原生set行为 - 所以仅靠方法存在性,无法确认“是不是真正的
set”
需要兼容性判断时,明确你要的是“可变性”还是“类型身份”
实际代码中常混淆这两个需求:
- 若你真正关心“能否修改”,应测
hasattr(obj, 'add') and not hasattr(obj, '__hash__')(注意:frozenset有__hash__,set没有) - 若你真正关心“是不是内置
set类型”,必须用type(obj) is set—— 这是唯一能排除子类、伪装类、协议实现的方案 - 用
isinstance(obj, collections.abc.MutableSet)可覆盖所有可变集合协议实现,但它会把自定义类也纳入,不满足“真正set”这个窄定义
在序列化或类型敏感场景下,type() 检查不可省略
比如 JSON 序列化器、ORM 字段校验、类型注解运行时检查,都依赖精确类型识别:
-
json.dumps({1, 2})报TypeError,因为set不可序列化;但frozenset({1, 2})同样报错,两者行为一致,但错误来源不同 - 若你想只允许原始
set(拒绝frozenset
和任何子类),就必须写
if type(data) is not set: raise TypeError(...) - 写成
if not isinstance(data, set)会导致frozenset被放过,而它显然不是你要的可变集合
真正难的不是怎么写判断,而是想清楚你到底在防御什么:是接口行为?可变性?还是类型血统。一旦目标模糊,type() 就成了最容易被绕过的漏洞点。
# ai
# 的是
# 这是
# 你要
# python
# 自定义
# 这两个
# 若你
# js
# json
# 对象
# if
# 子类
# 接口
# 序列化
# 比对
# 最可靠
# raise
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- LINUX的SELinux是什么_详解LINUX强
- c# Task.Yield 的作用是什么 它和Ta
- Windows蓝屏错误0x0000002C怎么解决
- Win11怎么设置虚拟内存_Windows 11优
- 如何使用Golang实现容器健康检查_监控和自动重
- Win11怎么关闭边缘滑动手势_Windows11
- Windows10系统怎么查看运行时间_Win10
- php订单日志怎么导出excel_php导出订单日
- Win11怎么关闭系统推荐内容_Windows11
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Golang如何测试HTTP中间件_Golang
- C++友元类使用场景_C++类间协作设计方式讲解
- Win11无法识别耳机怎么办_解决Win11插耳机
- Win10闹钟铃声怎么自定义 Win10闹钟自定义
- Win11无法拖拽文件到任务栏怎么办_Win11开
- Mac如何开启夜览模式_Mac护眼模式设置与定时
- Windows 11无法安全删除U盘提示设备正在使
- Win10如何更改开机密码_Windows10登录
- Python对象比较与排序_集合使用说明【指导】
- C#如何使用Channel C#通道实现异步通信
- c# Task.ConfigureAwait(tr
- c++怎么使用std::filesystem遍历文
- c++ stringstream用法详解_c++字
- Win11声音忽大忽小怎么办 Win11音频增强功
- PythonGIL机制理解_多线程限制解析【教程】
- 如何使用Golang defer优化性能_减少不必
- Win11任务栏颜色怎么改_Win11自定义任务栏
- Win10怎么关闭自动更新错误弹窗_Win10策略
- Win10怎样安装Word样式库_Win10安装W
- Windows10如何更改桌面图标间距_Win10
- Win11怎么修改DNS服务器 Win11设置DN
- PHP主流架构如何做单元测试_工具与流程【详解】
- Python函数参数高级用法_默认值与可变参数解析
- Win11怎么设置屏保时间_调整Win11屏幕保护
- Windows 11如何开启文件夹加密(EFS)_
- 如何使用Golang实现函数指针_函数变量与回调示
- Mac如何调整Dock栏大小和位置_Mac程序坞个
- 如何在 Go 中正确初始化结构体中的 map 字段
- mac怎么分屏_MAC双屏显示与分屏操作技巧【指南
- 短链接怎么用php递归还原_多层加密链接的处理法【
- 如何在Golang中处理JSON字段缺失_Gola
- Windows如何设置登录时的欢迎屏幕背景?(锁屏
- Win11文件扩展名怎么显示_Win11查看文件后
- Windows10蓝屏SYSTEM_SERVICE
- c++20的std::format怎么用 比pri
- Laravel 查询 JSON 列:高效筛选包含数
- Windows执行文件被SmartScreen拦截
- Win11开机速度慢怎么优化_Win11系统启动加
- Win11怎样安装钉钉客户端_Win11安装钉钉教
- 如何在Golang中写入XML文件_生成符合规范的


QQ客服