OOP实现摆线生成代码报'NoneType'无center属性错误
问题根因
报错'NoneType' object has no attribute 'center'的核心原因有三个:
- 类方法缩进错误:原代码中所有类成员方法没有缩进,不属于类作用域,Python语法上就不合法
- 方法调用顺序完全混乱:实例化后直接调用参数计算、几何生成方法,没有先执行画布初始化、图形元素创建的逻辑,
self.rolling_circle一直是初始化时的None值,访问其center属性必然报错 - 逻辑顺序倒置:
geom方法中用到的epicycloid多边形、点列表是在polygons方法中定义的,但原代码先调用geom后调用polygons,同样会触发空值错误;且geom方法的return写在for循环内部,第一次循环就会退出,根本无法生成完整摆线
类属性初始化规则
- 有明确默认业务值的属性,直接在
__init__方法中赋对应类型的默认值即可,比如销半径默认10、偏心距默认5这类固定参数,不需要设为None - 依赖后续方法计算、动态生成的对象(如画布坐标轴、matplotlib图形patch、计算得到的半径参数),如果
__init__执行阶段无法生成有效值,可以初始化为None,但必须保证调用用到该属性的方法前,已经通过前置流程给属性赋了有效值 - 循环内临时计算的中间变量(比如单次迭代的x/y坐标值),不需要放到
__init__中初始化,在使用的方法内直接定义即可
修复后可运行代码
import numpy as np import matplotlib.pyplot as plt class CycloidGeneration(): def __init__(self, axes=None, blank=None, plnt1=None, plnt2=None, plnt3=None, pin_radius=10, pin_circle_radius=120, eccentricity=5, p_pin_circle_radius=60, no_of_pins=16, p_number_of_pins=15, contraction=1, rolling_circle_line=None, rolling_circle=None): self.plnt1 = plnt1 self.plnt2 = plnt2 self.plnt3 = plnt3 self.pin_radius = pin_radius self.pin_circle_radius = pin_circle_radius self.eccentricity = eccentricity self.p_pin_circle_radius = p_pin_circle_radius self.p_number_of_pins = p_number_of_pins self.no_of_pins = no_of_pins self.blank = blank self.contraction = contraction self.rolling_circle_line = rolling_circle_line self.rolling_circle = rolling_circle self.epicycloid = None self.epicycloid_points = [] def setup_plot(self, amount): fig1 = plt.figure(figsize=(8, 8)) ax = plt.axes(xlim=(-amount, amount), ylim=(-amount, amount)) plt.axis('off') plt.ion() plt.show() return ax def plots(self): self.axes = self.setup_plot((self.pin_circle_radius+4*self.pin_radius)) self.contraction = self.rolling_circle_radius - self.eccentricity self.cycloid_base = plt.Circle((0, 0), self.cycloid_base_radius, fill=False, linestyle='--', lw=2) self.axes.add_patch(self.cycloid_base) self.rolling_circle = plt.Circle((0, 0), self.rolling_circle_radius, fill=False, lw=2) self.axes.add_patch(self.rolling_circle) self.rolling_circle_line = plt.Line2D((0, 1), (0, 0), lw=2, color='red') self.axes.add_line(self.rolling_circle_line) def prmtrs(self, pin_radius, pin_circle_radius, p_pin_circle_radius, number_of_pins, p_number_of_pins): self.pin_radius = pin_radius self.pin_circle_radius = pin_circle_radius self.p_pin_circle_radius = p_pin_circle_radius self.no_of_pins = number_of_pins self.p_number_of_pins = p_number_of_pins self.rolling_circle_radius = self.pin_circle_radius/self.no_of_pins self.reduction_ratio = self.no_of_pins + 1 self.cycloid_base_radius = self.reduction_ratio * self.rolling_circle_radius self.p_rolling_circle_radius = self.p_pin_circle_radius / self.p_number_of_pins self.p_reduction_ratio = self.p_number_of_pins - 1 self.p_cycloid_base_radius = self.p_reduction_ratio * self.p_rolling_circle_radius return self.p_cycloid_base_radius def geom(self): for angle in range(0, 360): # 绕摆线中心旋转滚动圆 self.x = ((self.cycloid_base_radius - self.rolling_circle_radius) * np.cos(np.radians(angle))) self.y = ((self.cycloid_base_radius - self.rolling_circle_radius) * np.sin(np.radians(angle))) self.rolling_circle.center = (self.x, self.y) self.point_x = (self.x + (self.rolling_circle_radius - self.contraction) *np.cos(np.radians(self.no_of_pins*-angle))) self.point_y = (self.y + (self.rolling_circle_radius - self.contraction) *np.sin(np.radians(self.no_of_pins*-angle))) self.rolling_circle_line.set_xdata((self.x, self.point_x)) self.rolling_circle_line.set_ydata((self.y, self.point_y)) self.epicycloid_points.append([self.point_x, self.point_y]) self.epicycloid.set_xy(self.epicycloid_points) plt.pause(0.01) return def polygons(self): # 主摆线多边形容器 self.epicycloid_points = [] self.epicycloid = plt.Polygon(self.blank, fill=False, closed=False, color='red', lw=2) self.axes.add_patch(self.epicycloid) # 行星轮1摆线容器 self.plnt1_epicycloid_points = [] self.plnt1_epicycloid = plt.Polygon(self.blank, fill=False, closed=False, color='red', lw=2) self.axes.add_patch(self.plnt1_epicycloid) # 行星轮2摆线容器 self.plnt2_epicycloid_points = [] self.plnt2_epicycloid = plt.Polygon(self.blank, fill=False, closed=False, color='red', lw=2) self.axes.add_patch(self.plnt2_epicycloid) return if __name__ == "__main__": geom = CycloidGeneration() geom.prmtrs(10,120,60,16, 15) geom.plots() geom.polygons() geom.geom() plt.ioff() plt.show()
主要修复点
- 修正类内部方法缩进,所有方法归属于类作用域
- 调整方法执行顺序:参数计算→画布与基础图形初始化→摆线多边形容器初始化→逐点生成摆线轨迹,保证所有属性在使用前已经完成初始化
- 把
geom方法中错误放在for循环内的return移到循环外部,保证360度轨迹点全部生成 - 补全
prmtrs方法的参数赋值逻辑,传入的销数量等参数正确覆盖实例默认值,避免传参不生效 - 增加绘图刷新、窗口驻留逻辑,避免动画过程卡顿、绘图窗口闪退
- 对动态生成的图形类属性在
__init__中提前声明,避免属性不存在报错
内容的提问来源于stack exchange,提问作者shoggananna
相关产品推荐
相关产品推荐

