描述符作为python中的实例属性
描述符对象需要存在于类中,而不是存在于实例中
因为那是实现的方式__getattribute__
。
一个简单的例子。考虑一个描述符:
class Prop(object):
def __get__(self, obj, objtype=None):
if obj is None:
return self
return obj._value * obj._multiplier
def __set__(self, obj, value):
if obj is None:
return self
obj._value = value
class Obj(object):
val = Prop()
def __init__(self):
self._value = 1
self._multiplier = 0
考虑每个obj具有多个Prop的情况:我将需要使用唯一的名称来标识值和乘数(如此处。具有每个实例的描述符对象将允许将_multiplier
(和_value
)存储在描述符本身中,从而简化了几样东西。
我知道以前也曾提出过类似的问题,但我没有找到真正的解释:
- 为什么以这种方式设计Python?
- 建议使用哪种方式存储描述符需要的信息,但按实例存储?
-
只有在类而不是实例上定义时,大量高级功能才起作用。例如,所有特殊方法。除了使代码评估更有效之外,这还使实例和类型之间的分隔变得清晰,否则分隔将容易崩溃(因为所有类型都是对象)。
我不确定这是如何推荐的,但是您可以在实例中存储从描述符实例到属性值的映射:
class Prop(object): def __get__(self, obj, objtype=None): if obj is None: return self return obj._value * obj._multiplier[self] def __set__(self, obj, value): if obj is None: return self obj._value = value class Obj(object): val = Prop() def __init__(self): self._value = 1 self._multiplier = {Obj.val: 0}
与其他两个建议的选项相比,它具有明显的优势:
- 每个实例的类破坏了面向对象并增加了内存使用;
- 覆盖
__getattribute__
是低效的(因为所有属性访问都必须通过覆盖的特殊方法进行访问)并且脆弱。
或者,您可以使用proxy属性:
class PerInstancePropertyProxy(object): def __init__(self, prop): self.prop = prop def __get__(self, instance, owner): if instance is None: return self return instance.__dict__[self.prop].__get__(instance, owner) def __set__(self, instance, value): instance.__dict__[self.prop].__set__(instance, value) class Prop(object): def __init__(self, value, multiplier): self.value = value self.multiplier = multiplier def __get__(self, instance, owner): if instance is None: return self return self.value * self.multiplier def __set__(self, instance, value): self.value = value class Obj(object): val = PerInstancePropertyProxy('val') def __init__(self): self.__dict__['val'] = Prop(1.0, 10.0) def prop(self, attr_name): return self.__dict__[attr_name]