Python使用Point类计算两点欧氏距离报无x属性错误及OOP用法疑问
报错原因
你当前的代码报错核心原因是:你没有为Point类定义名为x()的实例方法,__init__方法中你直接将坐标存储为实例的_x、_y属性,没有对应的获取方法自然无法调用x()、y()。
另外还有一个不影响运行但极易出错的写法问题:你在dist_to_point方法中将形参命名为Point,和你的类名完全重名,非常容易混淆类和实例,建议修改为other_point这类指向实例含义的命名。
问题解答
1. self的作用是什么?
self是Python类实例方法的默认第一个参数,指向调用该方法的实例本身,调用实例方法时不需要手动传值,Python会自动完成绑定。
比如你执行p1.dist_to_point(p2)时,dist_to_point方法中的self就自动对应p1这个实例,你才能通过self._x读取到p1自己的x坐标。
2. 访问Point实例的坐标必须用self._x/self._y的形式吗?
分两种场景:
- 访问当前方法所属实例的坐标:类的内部方法中必须通过
self才能访问实例自己的属性,直接写_x会被识别为局部变量,找不到对应的值。 - 访问其他Point实例的坐标:Python中开头的单下划线只是约定的「保护属性」标识,仅提示使用者尽量不要在类外部直接访问,语法上没有访问限制,所以你可以直接读取其他Point实例的
_x、_y属性。
3. 正确的距离计算方法怎么写?
你可以直接访问传入实例的_x、_y属性完成计算,修复后的dist_to_point方法如下:
def dist_to_point(self, other_point): dist = math.sqrt((self._x - other_point._x)**2 + (self._y - other_point._y)**2) return dist
如果你确实想要使用.x()的形式获取坐标,需要在类中补充定义getter方法,也可以用@property装饰器实现属性式调用:
# 方法1:普通getter方法 def x(self): return self._x def y(self): return self._y # 方法2:property装饰器,调用时不用加括号,直接用other_point.x即可 @property def x(self): return self._x @property def y(self): return self._y
修复后完整可运行代码
import math class Point(object): """A 2D point in the cartesian plane""" def __init__(self, x, y): self._x = x self._y = y def __repr__(self): return 'Point({}, {})'.format(self._x, self._y) def dist_to_point(self, other_point): dist = math.sqrt((self._x - other_point._x)**2 + (self._y - other_point._y)**2) return dist # 测试代码 p1 = Point(1,2) p2 = Point(4,6) print(p1.dist_to_point(p2)) # 输出5.0
内容的提问来源于stack exchange,提问作者CountDOOKU
相关产品推荐
相关产品推荐

