为什么在__init__函数中声明描述符类会破坏描述符功能?

时间:2009-06-16 21:55:48

标签: python descriptor

在下面的B类中,我希望每当您为__set__赋值时,都会调用A类中的B().a函数。相反,将值设置为B().a会使用值覆盖B().a。分配给C().a的C类工作正常,但我希望每个用户类都有一个单独的A实例,即我不希望在一个C()实例中更改'a'来改变'a'in所有其他情况。我写了几个测试来帮助说明问题。你能帮我定一个会传递test1和test2的类吗?

class A(object):
    def __set__(self, instance, value):
        print "__set__ called: ", value

class B(object):
    def __init__(self):
        self.a = A()

class C(object):
    a = A()

def test1( class_in ):
    o = class_in()
    o.a = "test"
    if isinstance(o.a, A):
        print "pass"
    else:
        print "fail"

def test2( class_in ):
    o1, o2 = class_in(), class_in()
    if o1.a is o2.a:
        print "fail"
    else:
        print "pass"

3 个答案:

答案 0 :(得分:5)

相应于documentation

  

当包含的类的实例时,以下方法仅适用   方法(所谓的描述符   class)出现在类字典中   另一种新式的,被称为   所有者类。在例子中   下面,“属性”指的是   属性名称是的关键字   所有者类“__dict__中的属性。   描述符只能实现为   新式课程本身。

所以你不能在实例上有描述符。

但是,由于描述符获取了用于访问它的实例的ref,只需将其用作存储状态的键,并且根据实例可以有不同的行为。

答案 1 :(得分:0)

这是一个可以通过原始测试的类,但在大多数情况下不要尝试使用它。它没有通过isinstance测试本身!

class E(object):
    def __new__(cls, state):
        class E(object):
            a = A(state)
            def __init__(self, state):
                self.state = state
        return E(state)

#>>> isinstance(E(1), E)
#False

答案 2 :(得分:0)

我被一个类似的问题所困扰,因为我想用具有描述符的属性对象进行分类。当我这样做时,我注意到所有对象中的属性都被覆盖,因此它们不是个体。

我提出了一个问题,结果答案就在这里:class attribute changing value for no reason

讨论描述符的好文档链接在这里:http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

上述链接的示例描述符如下:

class Numberise(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, instance, owner):
        if self.name not in instance.__dict__:
            raise (AttributeError, self.name)
        return '%o'%(instance.__dict__[self.name])

    def __set__(self, instance, value):
        print ('setting value to: %d'%value)
        instance.__dict__[self.name] = value