Python 中 __get__ 方法的内部结构

问题描述 投票:0回答:1

我正在摆弄描述符,结果碰壁了。我以为我可以像使用任何其他方法一样直接调用它,但显然,它似乎不一致或者我遗漏了一些东西。

假设我有一个用作描述符的坐标类:

class Coordinate:
   def __set_name__(self, owner, name):
      self._name = name

   def __get__(self, instance, owner):
      return instance.__dict__[self._name]

   def __set__(self, instance, value):
      try:
         instance.__dict__[self._name] = float(value)
      except ValueError:
         raise ValueError(f'"{self.__set_name__}" must be a number') from None

还有一个 Point 类,它有 2 个坐标属性:

class Point:
   x = Coordinate()
   y = Coordinate()

   def __init__(self, x, y):
      self.x = x
      self.y = y

假设我在主代码上创建了一个像这样的新点:

point1 = Point(12,5)

我知道如果我尝试这样做:

print(point1.x)

我将在控制台中得到这个:

12.0

我知道如果我尝试这个,它会失败:

print(point1.x.__get__(Point))

我的 get 方法将被调用,参数如下:

  • self:将是 point1.x,坐标实例。
  • instance:将是我的 point1,即 Point 实例。
  • owner:将成为Point 类。

所有这些都是因为参数的顺序。因为我有:

x.__get__()

x将是我的第一个论点。 然后自从我有了

point1.x.__get()
x 将是我的第一个参数,point1 将是我的第二个参数。

并且让 Point 类在括号内传递完成我想要的,但它仍然不起作用,因为即使 get 方法返回

12.0
,Python 现在将尝试调用 get 方法float (12.0) 由我的手动 get 调用返回,这将引发异常。

'float' object has no attribute '__get__'

所有这些对我来说都很有意义。 没有意义的是,当我尝试做这样的事情时:

print(Point.x.__get__(Point))

而不是像这样填充我的 get 方法参数:

  • self:将是 Point.x,在 Point 类中声明的坐标实例。
  • instance:将是对我的 Point 类本身的引用。
  • owner:也是对 Point 类本身的引用。

它将 instance 参数填充为 None。

为什么会发生这种情况?如果所有其他参数都正确传递,为什么它不填充对 Point 的引用? (self 和owner 参数都有预期值)。

python descriptor
1个回答
0
投票

当你这样做时:

Point.x.__get__(Point)

在事件到达

.__get__(Point)
部分之前它会出错,因为
Point.x
调用您的描述符,使用
instance=None
,完全符合您的预期,因为描述符是在类上调用的,而不是在任何实例上 .

© www.soinside.com 2019 - 2024. All rights reserved.