描述符作为python中的实例属性

发布于 2021-01-29 18:14:13

描述符对象需要存在于类中,而不是存在于实例中

因为那是实现的方式__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)存储在描述符本身中,从而简化了几样东西。

我知道以前也曾提出过类似的问题,但我没有找到真正的解释:

  1. 为什么以这种方式设计Python?
  2. 建议使用哪种方式存储描述符需要的信息,但按实例存储?
关注者
0
被浏览
47
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    只有在类而不是实例上定义时,大量高级功能才起作用。例如,所有特殊方法。除了使代码评估更有效之外,这还使实例和类型之间的分隔变得清晰,否则分隔将容易崩溃(因为所有类型都是对象)。

    我不确定这是如何推荐的,但是您可以在实例中存储从描述符实例到属性值的映射:

    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}
    

    与其他两个建议的选项相比,它具有明显的优势:

    1. 每个实例的类破坏了面向对象并增加了内存使用;
    2. 覆盖__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]
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看