我正在摆弄描述符,结果碰壁了。我以为我可以像使用任何其他方法一样直接调用它,但显然,它似乎不一致或者我遗漏了一些东西。
假设我有一个用作描述符的坐标类:
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 方法将被调用,参数如下:
所有这些都是因为参数的顺序。因为我有:
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 方法参数:
它将 instance 参数填充为 None。
为什么会发生这种情况?如果所有其他参数都正确传递,为什么它不填充对 Point 的引用? (self 和owner 参数都有预期值)。
当你这样做时:
Point.x.__get__(Point)
在事件到达
.__get__(Point)
部分之前它会出错,因为 Point.x
调用您的描述符,使用 instance=None
,完全符合您的预期,因为描述符是在类上调用的,而不是在任何实例上 .