设置了一个类级类型描述符的方法__

2024-04-20 09:57:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我的数据描述符同时适用于__set__和{}的对象。在

然而,类描述符似乎不支持__set__。这样做反而会用指定的值替换描述符对象本身。在

下面的代码演示了这一点

from __future__ import print_function

class Descriptor(object):
    def __get__(self, obj, cls):
        print('__get__')
    def __set__(self, obj, value):
        print('__set__')

class Class(object):
    descriptor = Descriptor()

print('Object')
a = Class()
a.descriptor
a.descriptor = 1

print('Class')
Class.descriptor
Class.descriptor = 2

哪些输出

^{pr2}$

如您所见,类级别__set__没有被调用。在

是否有一些解决方法或黑客(无论多么可怕)允许在类上使用__set__数据描述符?在

我只是想说清楚,我不想调用代码必须实现任何“黑客”。我希望调用代码能像上面预期的那样工作,但是任何黑客行为都是“幕后黑手”。在

使用Python2.7


Tags: 数据对象代码selfobjgetobjectdef
1条回答
网友
1楼 · 发布于 2024-04-20 09:57:44

我不想讨论整个描述符协议。我自己并没有完全理解这一点;事实上,你提醒了我,我需要停止懒惰,并投入其中。同时,我要说:

我所理解的是,描述符只会在实例上发挥其魔力。现在,你可能已经知道了,这就是为什么你想知道是否有黑客可以绕过这个限制。在

如果您对元类稍有了解,您就会知道类也是实例。类可以是类的实例,也可以是实例等等。这很好,因为你的要求看起来像这样:

class Descriptor(object):
    def __get__(self, obj, cls):
        print('__get__')
    def __set__(self, obj, value):
        print('__set__')

class MetaClass(type):
    descriptor = Descriptor()

class Class(object):
    __metaclass__ = MetaClass

# This will work fine when you do Class.descriptor, as you asked
# but it will raise an AttributeError if you do 
# a = Class()
# a.descriptor
# Read on for the full explanation...

MetaClass中定义的descriptor变量仅对Class类可见。任何试图调用Class的实例都将给您一个AttributeError。这是因为类的实例在搜索属性时,在搜索类的__dict__之前先搜索它们自己的__dict__,但它不会搜索到类的__metaclass__。现在,如果你想同时拥有它,并且对类和它的实例使用相同的变量名(尽管我不推荐它,因为它会引起混淆),那么可以这样做:

^{pr2}$

此时您可能会想知道:如果一个实例在搜索它的类之前搜索它自己的__dict__,那么如果Class.descriptor本质上是它自己的实例变量(来自元类POV),那么调用“Class.descriptor”怎么会不会选择“Class.descriptor”使用的相同描述符(正如您所观察到的那样,这将无法正常工作)?在

答案是数据描述符(同时定义了__get__和{}的描述符)与非数据描述符(只定义了__get__)相比,其优先级高于实例变量。换句话说,MetaClass中的descriptor变量是Class将选择的变量,因为它优先于Class自己的descriptor变量。Class实例也是如此,它自动获取在Class中定义的descriptor变量。在

我希望我没有把你弄糊涂。这些东西很容易被遗忘,我认为更是如此,因为它不是很常见,也没有必要了解这种水平的魔术大多数时间。我不得不在这件事上刷新我的记忆!好问题:)

相关问题 更多 >