能安全调用 vars() 的对象是:(1)未使用 slots 的自定义类实例;(2)模块对象;(3)部分函数对象(不推荐依赖)。vars() 本质返回 __dict__,故要求对象必须有可写的实例字典。

vars() 只能读取有 __dict__ 的对象,对内置类型、slots 类、命名元组等直接报错。
哪些对象能用 vars() 安全调用?
它本质是返回对象的 __dict__,所以前提是该对象:(1)由类定义且未使用 __slots__;(2)不是内置不可变类型(如 int、str、tuple);(3)不是 C 扩展类(如 datetime.datetime)。
常见可用场景:
- 你自己写的普通 class 实例(没设
__slots__) - 模块对象(
vars(sys)有效) - 函数对象(
vars(len)报错,但vars(my_func)有时可返回其闭包/属性,不推荐依赖)
典型错误:
立即学习“Python免费学习笔记(深入)”;
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
vars(42) # TypeError: vars() argument must have __dict__ attribute
from datetime import datetime vars(datetime.now()) # TypeError: ... no __dict__ attribute
vars() 和 dir() 的关键区别在哪?
dir() 返回所有可访问名称(包括继承的、特殊方法、类属性),但不区分来源、不带值;vars() 只返回实例自身的可写属性字典(键是字符串,值是实际对象),更轻量、更适合序列化或调试时看“当前状态”。
例如:
class A:
cls_attr = "I'm class"
def __init__(self):
self.inst_attr = "I'm instance"
<p>a = A()
vars(a) # {'inst_attr': "I'm instance"}
dir(a) # [..., 'cls_attr', 'inst_attr', '<strong>init</strong>', ...](长列表,含方法名)注意:vars(a) 不会包含 cls_attr,哪怕它能被 a.cls_attr 访问。
替代方案:当 vars() 失效时怎么办?
遇到 __slots__ 类、dataclass(默认无 __dict__)、或冻结的 NamedTuple,别硬刚 vars()。改用:
-
getattr(obj, attr)配合dir(obj)过滤出非私有、非方法的属性名(但可能漏掉动态设置的属性) - 对 dataclass,优先用
dataclasses.asdict(obj)(需未设frozen=True或手动处理) - 对
__slots__类,直接遍历obj.__slots__列表并用getattr()获取值 - 通用兜底(谨慎):
{k: getattr(obj, k) for k in dir(obj) if not k.startswith('_') and not callable(getattr(obj, k))}—— 性能差、可能误判、不保证顺序
真正难处理的是那些既没 __dict__、又没公开 slots、还屏蔽了 __slots__ 访问的 C 扩展对象——这时候就别强求“所有属性”,按需查文档或源码找字段名更实在。

















