【发布时间】:2017-09-08 17:19:11
【问题描述】:
我想定义一个函数,它返回__setattr__ 的一般实现,它使属性不可设置,除非它们是属性(我通常应该测试数据描述符,但那是以后的时间)。函数如下所示:
def make_setattr(doc='Immutable attributes'):
def __setattr__(self, name, value):
if isinstance(getattr(type(self), name, None), property):
super(type(self), self).__setattr__(name, value)
raise AttributeError('Please stop trying!')
__setattr__.__doc__ = doc
return __setattr__
这是一个显示用法的示例:
class A:
__setattr__ = make_setattr()
@property
def x(self):
return 1
@x.setter
def x(self, name):
pass
class B(A):
pass
这似乎适用于非属性属性:
>>> a = A()
>>> a.y = 1
AttributeError: Please stop trying!
>>> a.y
AttributeError: 'A' object has no attribute 'y'
>>> b = B()
>>> b.y = 1
AttributeError: Please stop trying!
>>> b.y
AttributeError: 'B' object has no attribute 'y'
但是,对于属性属性,它非常失败:
>>> a.x = 1
AttributeError: Please stop trying!
>>> b.x = 1
RecursionError: maximum recursion depth exceeded while calling a Python object
在a 上设置属性似乎完全忽略了x 是一个属性的事实。将其设置为b 会进入无限递归super(type(self), self).__setattr__(name, value)。这两个调用都好像super(type(self), self) 的结果返回了__setattr__ 的错误实现。
我试图通过删除super 的参数来缓解这种情况:super().__setattr__(name, value),但a.x = 1 和b.x = 1 都提高了
RuntimeError: super(): __class__ cell not found
如何在我的外部定义方法中找到并调用__setattr__ 的正确父实现?在这种情况下,如果可能的话,我想避免显式调用object.__setattr__。
【问题讨论】:
-
永远不要将
type(self)传递给super。 -
这听起来不错,但我很想知道为什么以及如何正确解决它。
-
我不确定调用
__setattr__是不是你想调用的——catch:是的,调用:我不太确定。您可以考虑改为调用描述符的__set__方法。 -
调用
__set__也可以,并且无需了解课程。 code this was probably based on 在类中定义了__setattr__,所以它可以只使用super().__setattr__。 -
明确调用
__set__确实意味着您不会获得任何其他超类__setattr__覆盖的效果。
标签: python python-3.x properties