关于python:为什么在描述符类的__get__中需要“if instance is None”?

why do you need “if instance is None” in __get__ of a descriptor class?

我从有效的python项目31中得到以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from weakref import WeakKeyDictionary
class Grade(object):
    def __init__(self):
        self._values = WeakKeyDictionary()
    def __get__(self, instance, instance_type):
        if instance is None: return self
        return self._values.get(instance, 0)

    def __set__(self, instance, value):
        if not (0 <= value <= 100):
            raise ValueError('Grade must be between 0 and 100')
        self._values[instance] = value


# Example 16
class Exam(object):
    math_grade = Grade()
    writing_grade = Grade()
    science_grade = Grade()

first_exam = Exam()
first_exam.writing_grade = 82
second_exam = Exam()
second_exam.writing_grade = 75
print('First ', first_exam.writing_grade, 'is right')
print('Second', second_exam.writing_grade, 'is right')

我想不出有任何理由把if instance is None: return self放在__get__中。一个Exam实例(或其他使用Grade的潜在类)如何可以是None实例?


Python中的会通None实例的描述符的访问时,在类中。

这是通过返回的self案例中可以访问的对象的类的描述,有没有在线的协议访问到ClassObj.__dict__['name_of_descriptor'](旁路)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
>>> class DemoDescriptor:
...     def __get__(self, instance, type_):
...         if instance is None:
...             print('Accesing descriptor on the class')
...             return self
...         print('Accessing descrtor on the instance')
...         return 'Descriptor value for instance {!r}'.format(instance)
...
>>> class DemoClass(object):
...     foo = DemoDescriptor()
...
>>> DemoClass.foo  # on the class
Accesing descriptor on the class
<__main__.DemoDescriptor object at 0x1041d3c50>
>>> DemoClass.__dict__['foo']  # bypassing the descriptor protocol
<__main__.DemoDescriptor object at 0x1041d3c50>
>>> DemoClass().foo  # on the instance
Accessing descrtor on the instance
'Descriptor value for instance <__main__.DemoClass object at 0x1041d3438>'

为您的特定的情况下,每个Exam.math_gradeExam.writing_grade或打电话,Exam.science_gradeGrade.__get__None的实例中,通过与Examfor the instance_type