[英]why do you need “if instance is None” in __get__ of a descriptor class?
I get the following example from Effective Python item 31: 我从Effective Python第31项获得以下示例:
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')
I can't think of any reason to have if instance is None: return self
in __get__
. if instance is None: return self
我想不出任何理由if instance is None: return self
在__get__
if instance is None: return self
。 How can an Exam
(or other potential classes using Grade
) instance be None
? Exam
(或使用Grade
其他潜在课程)实例如何才能成为None
?
Python will pass in None
for the instance when accessing the descriptor on the class. 在访问类的描述符时,Python将为实例传递None
。
By returning self
in that case you can access the descriptor object on the class without having to bypass the protocol (by accessing ClassObj.__dict__['name_of_descriptor']
). 通过在这种情况下返回self
,您可以访问类上的描述符对象,而无需绕过协议(通过访问ClassObj.__dict__['name_of_descriptor']
)。
>>> class DemoDescriptor:
... def __get__(self, instance, type_):
... if instance is None:
... print('Accessing descriptor on the class')
... return self
... print('Accessing descriptor on the instance')
... return 'Descriptor value for instance {!r}'.format(instance)
...
>>> class DemoClass(object):
... foo = DemoDescriptor()
...
>>> DemoClass.foo # on the class
Accessing 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 descriptor on the instance
'Descriptor value for instance <__main__.DemoClass object at 0x1041d3438>'
This is how the __get__
method implementations for function
and property
objects work too. 这也是function
和property
对象的__get__
方法实现的工作方式。
For your specific case, each of Exam.math_grade
, Exam.writing_grade
or Exam.science_grade
will call Grade.__get__
, passing in None
for the instance, and Exam
for the instance_type
. 对于您的具体情况, Exam.math_grade
, Exam.writing_grade
或Exam.science_grade
每一个都将调用Grade.__get__
,为实例传递None
,并为instance_type
传递Exam
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.