我试图实现一个类属性,其中 setter 只能被调用一次,我想知道如何最好地实现这一点?以及如何使其最“Pythonic”?
我考虑过的选项:
- 子类化并扩展内置
属性
。 - 装饰属性的 setter。
- 添加一个属性,用于保存每个 setter 的设置频率。
还有其他想法吗?
以及如何最好地实现的建议?
最佳答案
如果您经常使用它以及其他属性
功能,则对属性进行子类化是合适的。
由于属性的工作方式,这有点棘手 - 当一个人调用时
@prop.setter
,创建属性的新实例。下面的子类将起作用。
class FuseProperty(property):
def setter(self, func):
def fuse(instance, value):
name = f"_fuse_{self.fget.__name__}"
if not getattr(instance, name, False):
func(instance, value)
setattr(instance, name, True)
return super().setter(lambda instance, value: fuse(instance, value))
这是正在使用的。
In [24]: class A:
...: @FuseProperty
...: def a(self):
...: return self._a
...: @a.setter
...: def a(self, value):
...: self._a = value
...:
In [25]: a = A()
In [26]: a.a = 23
In [27]: a.a
Out[27]: 23
In [28]: a.a = 5
In [29]: a.a
Out[29]: 23
但是,如果这个“fuse”属性就是您所需要的,并且没有其他代码添加到 getter 和 setter,那么它可能会简单得多:您可以使用相同的机制创建一个全新的“Descriptor”类由 property
使用 - 这可能会好得多,因为您的“fuse”属性可以在一行中构建,而不需要 setter 和 getter 方法。
所需要的只是一个带有 __get__
和 __set__
方法的类 - 我们可以添加 __set_name__
来自动获取新的属性名称(其中property
本身没有,所以我们从上面的 fget
方法获取名称)
class FuseAttribute:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
return getattr(instance, f"_{self.name}")
def __set__(self, instance, value):
if not getattr(instance, f"_fuse_{self.name}", False):
setattr(instance, f"_{self.name}", value)
# add an else clause for optionally raising an error
setattr(instance, f"_fuse_{self.name}", True)
并使用它:
In [36]: class A:
...: a = FuseAttribute()
...:
In [37]: a = A()
In [38]: a.a = 23
In [39]: a.a
Out[39]: 23
In [40]: a.a = 5
In [41]: a.a
Out[41]: 23
关于python - 如何最好地实现一个只能调用一次 setter 的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69728924/