3

我正在尝试理解 Python 中的描述符。我似乎无法理解的是描述符方法中的实例和所有者是什么:

object.__get__(self, instance, owner)

现在我已经阅读了文档说:

所有者始终是所有者类,而实例是通过所有者访问属性的实例,或者当通过所有者访问属性时为 None。

不幸的是,我无法理解这意味着什么。所有者是否指类本身?类对象?那么实例传递给它的目的是什么?

4

3 回答 3

2

所有者是否指类本身?

是的。

类对象?

这是完全相同的事情。

那么实例传递给它的目的是什么?

描述符如何访问它在 else 上查找的实例?如果以内置property类型为例,它通过存储访问器函数并回调这些函数来工作。这些函数期望当前实例作为第一个参数(规范命名为“self”)。如果描述符没有得到当前实例,它显然不能将它传递给访问器。

于 2019-03-08T12:36:01.850 回答
1

这段代码可以说明这些关系:

class DescriptorClass:
    def __get__(self, instance, owner):
        return self, instance, owner

class OwnerClass:
    descr = DescriptorClass()

ownerinstance = OwnerClass()

self, instance, owner = ownerinstance.descr

assert self is OwnerClass.__dict__['descr']
assert instance is ownerinstance
assert owner is OwnerClass

self, instance, owner = OwnerClass.descr
assert instance is None
于 2019-03-08T13:16:38.150 回答
1

考虑这个

 __get__(self, instance, owner):

owner- 这是指创建描述符对象的类,记住描述符对象是在类级别定义的。

instance- 这是指owner您定义描述符对象的类的对象。

将 传递instance__get__描述符的方法的目的是确保我们知道并识别owner您正在从哪个类的对象访问描述符实例。

由于描述符对象是在类级别创建的,因此描述符类本身的简单实现可能会导致类的多个对象owner覆盖描述符实例的值。这是此类代码的示例

def __get__(self, instance, owner):
    return self.data

def __set__(self, instance, data):
    if value < 1:
        raise Exception("Negative or zero is not allowed")
    else:
        self.data = value

所以在上面的例子中, 的值仅存储在描述符实例中,如果您正在创建该类的多个对象并且假设这些对象正在设置 的值data,则此代码将产生严重的副作用。ownerdata

因此,为了解决这样的问题,您需要存储datain __dict__of的值,instance但是如果您无法访问instance描述符类本身,您将如何处理?因此,根据我的经验,这是instance描述符类的主要目的。作为解决上述问题并投入instance使用的参考,这里是代码

class DataDescriptor(object):
    def __init__(self, attribute):
        self.default = 100
        self.attribute = attribute

    def __get__(self, instance, owner):
        print('Getting the value of', self.attribute,
              '__get__ of Data descriptor invoked')
        return instance.__dict__.get(self.attribute, self.default)

    def __set__(self, instance, value=200):
        if value > 0:
            print('__set__ of Data descriptor invoked')
            instance.__dict__[self.attribute] = value
        else:
            sys.exit('Negative value not allowed')
于 2019-03-08T13:53:57.360 回答