You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OOP实现摆线生成代码报'NoneType'无center属性错误

问题根因

报错'NoneType' object has no attribute 'center'的核心原因有三个:

  1. 类方法缩进错误:原代码中所有类成员方法没有缩进,不属于类作用域,Python语法上就不合法
  2. 方法调用顺序完全混乱:实例化后直接调用参数计算、几何生成方法,没有先执行画布初始化、图形元素创建的逻辑,self.rolling_circle一直是初始化时的None值,访问其center属性必然报错
  3. 逻辑顺序倒置: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:39:06