Python中__get__方法内部机制疑问:调用时instance为何为None?
Python描述符__get__方法参数的疑惑解析
首先明确Python描述符协议中__get__方法的参数规则:
- 当通过实例对象访问描述符属性(如
point1.x):Python会自动调用描述符实例.__get__(实例对象, 所属类),此时instance参数是具体的实例,owner是该实例的类。 - 当通过类访问描述符属性(如
Point.x):Python会自动调用描述符实例.__get__(None, 所属类),此时instance参数为None——这是Python描述符协议的明确规定,用来区分是类层面的访问还是实例层面的访问。
你遇到的问题原因
你手动调用Point.x.__get__(Point)时,存在两个关键问题:
- 参数传参错误:
__get__方法需要接收三个参数(self会自动绑定到描述符实例Point.x,另外需要显式传入instance和owner)。你只传了一个参数,Python会直接抛出TypeError,提示缺少owner参数,根本无法正常执行到你预期的逻辑。 - 逻辑适配问题:即便你补全参数为
Point.x.__get__(Point, Point),此时instance是Point类对象,但你的__get__方法试图访问instance.__dict__[self._name]——而Point类的__dict__中,self._name对应的是'x',其值是Coordinate描述符实例本身,并非你期望的数值(数值仅存储在实例对象的__dict__中,比如point1.__dict__['x'])。
另外,你直接访问Point.x时触发的自动调用,会传入instance=None,而你的__get__方法没有处理instance为None的情况,试图访问None.__dict__会直接抛出AttributeError。
修正建议
如果希望你的描述符支持类访问场景,可以修改__get__方法,处理instance为None的情况:
class Coordinate: def __set_name__(self, owner, name): self._name = name def __get__(self, instance, owner): if instance is None: # 类访问时返回描述符本身,或者自定义的类层面信息 return self return instance.__dict__[self._name] def __set__(self, instance, value): try: instance.__dict__[self._name] = float(value) except ValueError: raise ValueError(f'"{self._name}" must be a number') from None
修改后:
- 访问
point1.x会返回实例存储的数值12.0 - 访问
Point.x会返回Coordinate描述符实例本身,不会报错
正确的手动调用示例
- 模拟实例访问:
Point.x.__get__(point1, Point)→ 返回12.0 - 模拟类访问:
Point.x.__get__(None, Point)→ 返回描述符实例本身
内容的提问来源于stack exchange,提问作者Ricardo Ianelli
相关产品推荐
相关产品推荐

