setattr 如何避免无限递归的防护写法
发布时间 - 2026-01-23 00:00:00 点击率:次setattr在自定义__setattr__中触发无限递归,因所有属性赋值均调用该方法;安全做法是直接操作self.__dict__[name] = value(无__slots__时)或调用object.__setattr__(self, name, value)。
为什么 setattr 在自定义 __setattr__ 里会触发无限递归
当你在类的 __setattr__ 方法内部直接调用 setattr(self, name, value),Python 会再次进入同一个 __setattr__,形成死循环。这不是 bug,而是机制:所有属性赋值(包括 self.x = y 和 setattr(self, ...))都会走 __setattr__。
标准防护写法:绕过自定义逻辑,直写实例字典
最常用、最安全的方式是跳过 __setattr__,把值直接写进实例的 __dict__:
def __setattr__(self, name, value):
if name == "special_flag":
# 自定义逻辑
super().__setattr__(name, value.upper()) # 或其他处理
else:
# 防护:不触发 __setattr__,避免递归
self.__dict__[name] = value
-
self.__dict__[name] = value是底层字典操作,完全绕过__setattr__ - 适用于大多数普通属性;但对使用
__slots__的类不生效(此时需用object.__setattr__(self, name, value)) - 注意:如果类有 property 或描述符,这种写法会跳过它们的 setter,只写入实例字典 —— 这正是你想要的「绕过」行为
替代方案:用 object.__setattr__ 显式委托
当类继承链复杂,或你希望保持与父类 __setattr__ 行为一致(比如父类做了验证),应显式调用基类实现:
def __setattr__(self, name, value):
if name == "counter":
if not isinstance(value, int):
raise TypeError("counter must be int")
# 委托给 object.__setattr__,不触发当前类重写的 __setattr__
object.__setattr__(self, name, value)
else:
super().__setattr__(name, value) # 或继续委托给父类
-
object.__setattr__(self, name, value)是 Python 属性赋值的最终实现,不经过任何自定义__setattr__ - 比
self.__dict__更通用:兼容__slots__、描述符、property setter(只要它们没被覆盖) - 不要写成
super().__setattr__(...)—— 如果父类也重写了__setattr__,仍可能递归
容易踩的坑:你以为绕过了,其实没绕开
以下写法看似“手动”,实则仍在触发 __setattr__:
-
self.name = value→ 触发当前__setattr__ -
setattr(self, name, value)→ 触发当前__setattr__ -
self.__dict__.update({name: value})→ 看似字典操作,但某些情况下(如__dict__被代理或封装)可能间接触发 - 在
__init__中未做防护就调用setattr→ 同样递归,因为__init__里self.x = y也会走__setattr__
真正安全的只有两种:

self.__dict__(无 __slots__ 时),或明确调用 object.__setattr__。其余都是幻觉。
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
利用JavaScript实现拖拽改变元素大小
Laravel Livewire是什么_使用Laravel Livewire构建动态前端界面
成都网站制作公司哪家好,四川省职工服务网是做什么用?
在Oracle关闭情况下如何修改spfile的参数
WordPress 子目录安装中正确处理脚本路径的完整指南
创业网站制作流程,创业网站可靠吗?
如何用IIS7快速搭建并优化网站站点?
如何用wdcp快速搭建高效网站?
Laravel怎么创建自己的包(Package)_Laravel扩展包开发入门到发布
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
英语简历制作免费网站推荐,如何将简历翻译成英文?
公司门户网站制作流程,华为官网怎么做?
如何用低价快速搭建高质量网站?
java中使用zxing批量生成二维码立牌
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
如何在服务器上三步完成建站并提升流量?
如何在万网开始建站?分步指南解析
Laravel如何使用Livewire构建动态组件?(入门代码)
黑客入侵网站服务器的常见手法有哪些?
Python文件异常处理策略_健壮性说明【指导】
如何续费美橙建站之星域名及服务?
如何自定义建站之星模板颜色并下载新样式?
如何在万网利用已有域名快速建站?
标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析
Android 常见的图片加载框架详细介绍
,南京靠谱的征婚网站?
PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】
Laravel如何为API生成Swagger或OpenAPI文档
北京网站制作公司哪家好一点,北京租房网站有哪些?
如何用免费手机建站系统零基础打造专业网站?
如何在阿里云部署织梦网站?
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
香港网站服务器数量如何影响SEO优化效果?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
公司网站制作价格怎么算,公司办个官网需要多少钱?
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
jQuery 常见小例汇总
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能
百度浏览器网页无法复制文字怎么办 百度浏览器复制修复
猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】
如何在万网自助建站中设置域名及备案?
laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析
Laravel如何使用Telescope进行调试?(安装和使用教程)
太平洋网站制作公司,网络用语太平洋是什么意思?
历史网站制作软件,华为如何找回被删除的网站?
JavaScript如何实现路由_前端路由原理是什么
Laravel如何升级到最新版本?(升级指南和步骤)
Android仿QQ列表左滑删除操作
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用

