Mad*_*ist 3 python properties python-3.x
我有一个类,它使用__slots__并通过覆盖__setattr__始终引发错误来使它们几乎不可变:
class A:
__slots__ = ['a', 'b', '_x']
def __init__(self, a, b):
object.__setattr__(self, 'a', a)
object.__setattr__(self, 'b', b)
def __setattr__(self, attr, value):
raise AttributeError('Immutable!')
@property
def x():
return self._x
@x.setter
def x(value):
object.__setattr__(self, '_x', value)
Run Code Online (Sandbox Code Playgroud)
在这里,“私有”属性_x是与某些自定义硬件交互的复杂操作的占位符。
由于x是财产,我希望能够做类似的事情
inst = A(1, 2)
inst.x = 3
Run Code Online (Sandbox Code Playgroud)
相反,我看到了我的AttributeError消息Immutable!。
这里有许多明显的解决方法,例如删除自定义__setattr__(我不想这样做)或将其重写为
def __setattr__(self, attr, value):
if attr != 'x':
raise AttributeError('Immutable!')
super().__setattr__(attr, value)
Run Code Online (Sandbox Code Playgroud)
这似乎是一种尴尬的方法,如果我开始添加更多类似的属性,就有可能变得不成比例。
__slots__真正的问题是,我不明白为什么和财产之间没有冲突,但__setattr__和财产之间却有冲突。查找顺序发生了什么,是否有另一种更优雅的解决方法来解决这个问题?
__slots__真正的问题是,我不明白为什么和财产之间没有冲突,但__setattr__和财产之间却有冲突。
__slots__和两者都通过提供相应属性的描述符property来实现属性查找。的存在阻止了任意实例属性的创建,不是通过对 执行任何操作,而是通过阻止创建. 而其他描述符不依赖于实例,因此它们不受影响。__slots____setattr____dict__property__dict__
但是,__setattr__处理所有属性分配,这意味着描述符调用是__setattr__的责任。如果您__setattr__不处理描述符,则不会处理描述符,并且property不会调用设置器。
对于这个问题还有另一种更优雅的解决方法吗?
您可以明确仅允许属性:
class A:
...
def __setattr__(self, name, value):
if not isinstance(getattr(type(self), name, None), property):
raise AttributeError("Can't assign to attribute " + name)
super().__setattr__(name, value)
Run Code Online (Sandbox Code Playgroud)
或者您可以明确拒绝对插槽的分配,并将其他属性分配委托给super().__setattr__:
class A:
...
def __setattr__(self, name, value):
if isinstance(getattr(type(self), name, None), _SlotDescriptorType):
raise AttributeError("Can't assign to slot " + name)
super().__setattr__(name, value)
# Seems to be the same as types.MemberDescriptorType,
# but the docs don't guarantee it.
_SlotDescriptorType = type(A.a)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1200 次 |
| 最近记录: |