不会自动报错,但默认抛出attributeerror;必须显式传入第三个参数作fallback,否则等同obj.missing;默认值禁用可变对象,用户输入属性名需校验或白名单过滤。

getattr 读取不存在的属性时会报错吗?
不会自动报错,但默认行为是抛出 AttributeError——这恰恰是多数人踩坑的起点。你写 getattr(obj, 'missing'),没给默认值,它就炸;给了默认值(比如 getattr(obj, 'missing', None)),才安全返回。
常见错误现象:AttributeError: 'User' object has no attribute 'age',结果程序直接中断,而本意只是“查不到就算了”。
- 必须显式传入第三个参数作为 fallback,否则等同于直接访问
obj.missing - 默认值别用可变对象(如
[]或{}),避免被意外修改共享状态 - 如果属性名来自用户输入或配置文件,务必加一层校验:先用
hasattr(obj, name)判断再getattr,或者直接靠默认值兜底
setattr 写入私有属性(_开头)或只读属性会成功吗?
会成功,Python 不拦你——这是最危险的“看起来正常,其实埋雷”的点。比如对 dataclass 实例或带 @property 的类调用 setattr(obj, '_internal_flag', True),代码不报错,但后续逻辑可能彻底失效。
使用场景:动态设置配置、反射初始化、测试 mock 对象……但一旦越过封装边界,维护成本陡增。
立即学习“Python免费学习笔记(深入)”;
SmartB2B 是一款基于PHP、MySQL、Smarty的B2B行业电子商务网站管理系统,系统提供了供求模型、企业模型、产品模型、人才招聘模型、资讯模型等模块,适用于想在行业里取得领先地位的企业快速假设B2B网站,可以运行于Linux与Windows等多重服务器环境,安装方便,使用灵活。 系统使用当前流行的PHP语言开发,以MySQL为数据库,采用B/S架构,MVC模式开发。融入了模型化、模板
-
setattr对任何属性名都尝试写入,不管是不是@property、__slots__限制,甚至__dict__不可写时也会静默失败(取决于对象实现) - 想安全赋值,先检查目标是否支持:用
hasattr(type(obj), attr_name)看是否有对应@property的 setter,或查obj.__dict__是否存在(简单对象) - 生产环境慎用
setattr修改业务模型字段;宁可用明确的update()方法或数据验证层拦截
getattr/setattr 在 getattr(obj, '__dict__') 和 __slots__ 类上的表现差异
差异极大:普通类靠 __dict__ 存属性,getattr 能读所有动态添加的键;而启用 __slots__ 的类没有 __dict__,getattr 只能读预定义的 slot 名,其余一概报错(即使你用 setattr 强行塞进去,也进不了实例字典)。
性能影响:启用 __slots__ 后 getattr 略快(跳过 __dict__ 查找),但灵活性归零;兼容性上,很多依赖 __dict__ 的工具(如 copy.deepcopy、序列化库)会直接失效。
- 用
getattr(obj, '__dict__', {})安全获取属性字典,避免因__slots__导致的AttributeError - 判断类是否用了
__slots__:检查hasattr(cls, '__slots__')且'__dict__' not in cls.__slots__ - 不要在
__slots__类上依赖setattr动态新增字段——它要么失败,要么被忽略(取决于 Python 版本和定义方式)
用 getattr/setattr 做配置驱动逻辑时,如何防止执行任意代码?
当属性名来自外部(如 JSON 配置、URL 参数),getattr(obj, user_input) 就成了潜在的代码执行入口——如果用户传入 '__init__' 或 '__subclasses__',你就暴露了内部结构。
容易被忽略的地方:很多人只过滤下划线开头,却忘了双下划线方法(__ 开头结尾)和内置属性(如 __class__、__globals__)才是真正的风险点。
- 白名单优先:只允许一组预定义的属性名,而不是黑名单过滤
__ - 用
re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', attr_name)做基础命名校验,再结合白名单二次确认 - 对敏感对象(如 Flask
request、DjangoModel实例),禁止任何反射操作,改用显式映射表转换









