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

发布于 2024-07-24 07:24:24 字数 759 浏览 5 评论 0原文

在下面的 B 类中,我希望每当您为 B().a 赋值时就调用 A 类中的 __set__ 函数。 相反,将值设置为 B().a 会使用该值覆盖 B().a。 分配给 C().a 的 C 类工作正常,但我想为每个用户类拥有一个单独的 A 实例,即我不想在 C( ) 在所有其他情况下更改“a”。 我编写了几个测试来帮助说明问题。 你能帮我定义一个同时通过 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"

In class B below I wanted the __set__ function in class A to be called whenever you assign a value to B().a . Instead, setting a value to B().a overwrites B().a with the value. Class C assigning to C().a works correctly, but I wanted to have a separate instance of A for each user class, i.e. I don't want changing 'a' in one instance of C() to change 'a' in all other instances. I wrote a couple of tests to help illustrate the problem. Can you help me define a class that will pass both test1 and 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"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萌辣 2024-07-31 07:24:24

根据文档

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

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

但是,由于描述符获取对用于访问它的实例的引用,因此只需将其用作存储状态的键,您就可以根据实例具有不同的行为。

Accordingly to the documentation:

The following methods only apply when an instance of the class containing
the method (a so-called descriptor
class) appears in the class dictionary
of another new-style class
, known as
the owner class. In the examples
below, “the attribute” refers to the
attribute whose name is the key of the
property in the owner class’ __dict__.
Descriptors can only be implemented as
new-style classes themselves.

So you can't have descriptors on instances.

However, since the descriptor gets a ref to the instance being used to access it, just use that as a key to storing state and you can have different behavior depending on the instance.

人间不值得 2024-07-31 07:24:24

这是一个可以通过原始测试的类,但在大多数情况下不要尝试使用它。 它本身未通过 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

Here's a class that can pass the original tests, but don't try using it in most situations. it fails the isinstance test on itself!

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
忘年祭陌 2024-07-31 07:24:24

我遇到了类似的问题,因为我想对具有由描述符控制的属性的对象进行分类。 当我这样做时,我注意到所有对象中的属性都被覆盖,因此它们不是单独的。

我提出了一个问题,结果答案在这里:类属性无缘无故改变值

这里有一个讨论描述符的良好文档链接: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

I was bitten by a similar issue in that I wanted to class objects with attributes governed by a descriptor. When I did this, I noticed that the attributes were being overwritten in all of the objects such that they weren't individual.

I raised a SO question and the resultant answer is here: class attribute changing value for no reason

A good document link discussing descriptors is here: http://martyalchin.com/2007/nov/24/python-descriptors-part-2-of-2/

An example descriptor from the aforementioned link is below:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文