同一Python对象的实例变量为何同时引用不同对象(arcpy场景)
问题原因分析
- 首先你观察到
param和param2的id完全一致,说明二者本质上就是同一个Python对象,不存在两个不同实例的情况。 - 二者
filter属性id不同的核心原因来自你代码中passthrough_attr装饰的property的实现逻辑:
每次访问filter属性时,getter方法都会执行getattr(self._arc_object, 'filter'),而ArcGIS底层返回原生filter对象后,会自动封装为新的Filter类Python实例,相当于你每次访问filter属性都会生成一个新的Python包装对象,哪怕底层对应的原生ArcGIS filter对象自始至终都是同一个。
你可以做个简单验证:连续两次打印id(param.filter),得到的id也一定是不同的,这和你访问param2.filter的表现完全一致。
该现象的含义
这个表现说明你拿到的Filter类Python实例只是底层原生ArcGIS对象的临时包装层:
- 你修改
filter的type、list等属性时,这些属性本身也是passthrough_attr装饰的透传属性,修改会直接作用到底层的原生ArcGIS对象上,不会受包装层实例不同的影响。 - 你无法通过比较两个
filterPython实例的id来判断它们是否对应同一个底层原生过滤器,所有对filter属性的修改最终都会同步生效,符合你最开始的预期。
是否可以忽略/阻止
- 如果你只是常规修改过滤器的配置,完全可以忽略这个现象,不会影响业务功能正常运行。
- 如果你需要让同一个
Parameter实例多次访问filter属性都返回同一个Python包装对象,可以修改filter属性的实现逻辑,增加实例级缓存即可,参考修改思路:
class Parameter(mixins.ParameterMixin,_BaseArcObject): # 替换原来的filter = passthrough_attr('filter') @property def filter(self): if not hasattr(self, '_cached_filter'): self._cached_filter = getattr(self._arc_object, 'filter') return self._cached_filter @filter.setter def filter(self, val): self._cached_filter = val setattr(self._arc_object, 'filter', val)
内容的提问来源于stack exchange,提问作者Zeygon
相关产品推荐
相关产品推荐

