鱼C论坛

 找回密码
 立即注册
查看: 1502|回复: 4

[已解决]关于调用函数报错未定义

[复制链接]
发表于 2020-3-25 10:57:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
    我在新的代码里想调用我之前写的一个仿真模型,将之前的仿真代码用def封装成了一个函数,我是直接把整个仿真代码搬到def里面了,在运行的时候一直在报错说这个封装函数中的一个变量未定义,但是在仿真代码文件里是能够正常运行了,网上查了说各种原因都有,希望有大神帮我看下代码
  1. from tkinter import *
  2. from tkinter import messagebox
  3. import os
  4. import tkinter as tk


  5. #def Introduction():  # 定义简介

  6. def Simulation():     # 定义模拟仿真函数
  7.     import numpy as np
  8.     import matplotlib as mpl
  9.     mpl.use("TkAgg")
  10.     from matplotlib import pyplot as plt

  11.     import matplotlib.animation as animmation

  12.     r1 = 10  # 地球环绕轨迹的半径
  13.     r2 = 1  # 月球环绕轨迹的半径
  14.     omega1 = 2 * np.pi  # 地球运动的角速度
  15.     omega2 = 24 * np.pi  # 地球自转速度
  16.     phi = 5.1454 * np.pi / 180  # 地球自转轴角

  17.     def update(data):
  18.         # 随时间t变换设置新的地球位置的坐标,也即是随animmation.FuncAnimation函数的帧数参数变化每一帧的不同坐标位置的图片对象参数
  19.         global line1, line2, line3
  20.         line1.set_data([data[0], data[1]])
  21.         line1.set_3d_properties(data[2])
  22.         line2.set_data([data[3], data[4]])
  23.         line2.set_3d_properties(data[5])
  24.         line3.set_data([data[6], data[7]])
  25.         line3.set_3d_properties(data[8])
  26.         return line1, line2, line3,

  27.     def init():  # 地球的起始位置
  28.         global line1, line2, line3
  29.         ti = 0
  30.         t = t_drange[np.mod(ti, t_dlen)]
  31.         xt1 = x0 + r1 * np.cos(omega1 * t)
  32.         yt1 = y0 + r1 * np.sin(omega1 * t)
  33.         zt1 = z0 + 0
  34.         xt2 = xt1 + r2 * np.sin(omega2 * t)
  35.         yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  36.         zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
  37.         xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
  38.         yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  39.         zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
  40.         line1, = ax.plot([xt1], [yt1], [zt1], marker='o', color='blue', markersize=8)
  41.         line2, = ax.plot([xt2], [yt2], [zt2], marker='o', color='orange', markersize=4)
  42.         line3, = ax.plot(xt21, yt21, zt21, color='purple')
  43.         return line1, line2, line3

  44.     def data_gen():  # 随时间t变换的地球和月球坐标,也即是animmation.FuncAnimation函数的帧数参数
  45.         global x0, y0, z0, t_dlen
  46.         data = []
  47.         for ti in range(1, t_dlen):
  48.             t = t_drange[ti]
  49.             xt1 = x0 + r1 * np.cos(omega1 * t)
  50.             yt1 = y0 + r1 * np.sin(omega1 * t)
  51.             zt1 = z0
  52.             xt2 = xt1 + r2 * np.sin(omega2 * t)
  53.             yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  54.             zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
  55.             xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
  56.             yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  57.             zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
  58.             data.append([xt1, yt1, zt1, xt2, yt2, zt2, xt21, yt21, zt21])
  59.         return data

  60.     t_range = np.arange(0, 1 + 0.005, 0.005)  # 设置环绕一周时间的范围以及运动间隔时间
  61.     t_drange = np.arange(0, 1, 0.005)
  62.     t_len = len(t_range)
  63.     t_dlen = len(t_drange)
  64.     # sun's coordination
  65.     x0 = 0
  66.     y0 = 0
  67.     z0 = 0
  68.     # 地球轨道
  69.     x1 = x0 + r1 * np.cos(omega1 * t_range)
  70.     y1 = y0 + r1 * np.sin(omega1 * t_range)
  71.     z1 = z0 + np.zeros(t_len)

  72.     # 月球轨道
  73.     x2 = x1 + r2 * np.sin(omega2 * t_range)
  74.     y2 = y1 + r2 * np.cos(omega2 * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  75.     z2 = z1 + (y2 - y1) * np.tan(phi)

  76.     f = plt.figure(figsize=(6, 6))  # 绘图的画布
  77.     ax = f.add_subplot(111, projection='3d')  # 设置3d坐标系
  78.     ax.set_title("Sun-Earth-Moon Model")  # 设置图像标题(太阳-地球-月亮转动模型)

  79.     ax.plot([0], [0], [0], marker='o', color='red', markersize=16)  # 绘制太阳的各种属性
  80.     ax.plot(x1, y1, z1, 'r')  # 绘制地球图像
  81.     ax.plot(x2, y2, z2, 'b')  # 绘制月球图像
  82.     ax.set_xlim([-(r1 + 2), (r1 + 2)])  # 太阳用动模型在坐标系中的范围
  83.     ax.set_ylim([-(r1 + 2), (r1 + 2)])  # 地球用动模型在坐标系中的范围
  84.     ax.set_zlim([-5, 5])  # 月球用动模型在坐标系中的范围

  85.     # 红色球体代表太阳,蓝色球体代表地球,橙色球体代表月亮
  86.     line1, = ax.plot([], [], [], marker='o', color='blue', markersize=8, animated=True)
  87.     line2, = ax.plot([], [], [], marker='o', color='orange', markersize=4, animated=True)
  88.     line3, = ax.plot([], [], [], color='purple', animated=True)

  89.     # 将上述函数对象传如animmation.FuncAnimation函数以生成连读的地球运动模型
  90.     ani = animmation.FuncAnimation(f, update, frames=data_gen(), init_func=init, interval=20)

  91.     plt.show()


  92. #def Exercise():      # 定义演习函数
  93. #def Assessment():    #定义考核函数

  94. # 创建窗口
  95. app = Tk()

  96. # 定义窗口标题
  97. app.title("用Tkinter模块创建软件框架")

  98. # 设置长宽       这里的x是小写的,有点类似于乘号    宽 x 高
  99. app.geometry("800x800")

  100. # 定义窗口内容为theLabel
  101. theLabel = Label(app,  text="毕设草稿:气象部门工作方案", font="楷体 15", fg="green")
  102. # grid就是定位,网格式布局
  103. theLabel.grid()

  104. # 添加按钮
  105. # command 是点击按钮之后触发的事件
  106. button1 = Button(app, text="内容介绍", width=10, height=3)
  107. button1.grid(row=8, column=0, sticky=E)

  108. button2 = Button(app, text="仿真模型", width=10, height=3,command=Simulation)
  109. button2.grid(row=10, column=0, sticky=E)

  110. button3 = Button(app, text="实战演练", width=10, height=3)
  111. button3.grid(row=12, column=0, sticky=E)

  112. button4 = Button(app, text="进入考核", width=10, height=3)
  113. button4.grid(row=14, column=0, sticky=E)

  114. app.mainloop()
复制代码


最佳答案
2020-3-25 11:18:14
t_dlen在你的程序中出现了四次,都在函数Simulation 中,
第一次出现是在init函数中,直接出现在了右侧,这里尚未定义该变量,而且在你所封装的函数Simulation 外也没有定义过这个变量
第二次和第三次都是出现在global关键字之后,但是并没有这个名为t_dlen的全局变量
第四次才是出现在赋值操作符左侧,相当于定义了一个Simulation 函数内的局部变量。

你把这些变量的定义拉到Simulation 的前端,将那些函数向后放。
还有就是将那两个global改为nonlocal
报错.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-3-25 11:09:24 | 显示全部楼层
试试这样
  1. from tkinter import *
  2. from tkinter import messagebox
  3. import os
  4. import tkinter as tk


  5. #def Introduction():  # 定义简介

  6. def Simulation():     # 定义模拟仿真函数
  7.     import numpy as np
  8.     import matplotlib as mpl
  9.     mpl.use("TkAgg")
  10.     from matplotlib import pyplot as plt

  11.     import matplotlib.animation as animmation

  12.     r1 = 10  # 地球环绕轨迹的半径
  13.     r2 = 1  # 月球环绕轨迹的半径
  14.     omega1 = 2 * np.pi  # 地球运动的角速度
  15.     omega2 = 24 * np.pi  # 地球自转速度
  16.     phi = 5.1454 * np.pi / 180  # 地球自转轴角

  17.     def update(data):
  18.         # 随时间t变换设置新的地球位置的坐标,也即是随animmation.FuncAnimation函数的帧数参数变化每一帧的不同坐标位置的图片对象参数
  19.         global line1, line2, line3
  20.         line1.set_data([data[0], data[1]])
  21.         line1.set_3d_properties(data[2])
  22.         line2.set_data([data[3], data[4]])
  23.         line2.set_3d_properties(data[5])
  24.         line3.set_data([data[6], data[7]])
  25.         line3.set_3d_properties(data[8])
  26.         return line1, line2, line3,

  27.     def init():  # 地球的起始位置
  28.         global line1, line2, line3
  29.         ti = 0
  30.         t = t_drange[np.mod(ti, t_dlen)]
  31.         xt1 = x0 + r1 * np.cos(omega1 * t)
  32.         yt1 = y0 + r1 * np.sin(omega1 * t)
  33.         zt1 = z0 + 0
  34.         xt2 = xt1 + r2 * np.sin(omega2 * t)
  35.         yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  36.         zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
  37.         xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
  38.         yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  39.         zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
  40.         line1, = ax.plot([xt1], [yt1], [zt1], marker='o', color='blue', markersize=8)
  41.         line2, = ax.plot([xt2], [yt2], [zt2], marker='o', color='orange', markersize=4)
  42.         line3, = ax.plot(xt21, yt21, zt21, color='purple')
  43.         return line1, line2, line3

  44.     t_range = np.arange(0, 1 + 0.005, 0.005)  # 设置环绕一周时间的范围以及运动间隔时间
  45.     t_drange = np.arange(0, 1, 0.005)
  46.     t_len = len(t_range)
  47.     t_dlen = len(t_drange)

  48.     def data_gen():  # 随时间t变换的地球和月球坐标,也即是animmation.FuncAnimation函数的帧数参数
  49.         global x0, y0, z0, t_dlen
  50.         data = []
  51.         for ti in range(1, t_dlen):
  52.             t = t_drange[ti]
  53.             xt1 = x0 + r1 * np.cos(omega1 * t)
  54.             yt1 = y0 + r1 * np.sin(omega1 * t)
  55.             zt1 = z0
  56.             xt2 = xt1 + r2 * np.sin(omega2 * t)
  57.             yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  58.             zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
  59.             xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
  60.             yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  61.             zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
  62.             data.append([xt1, yt1, zt1, xt2, yt2, zt2, xt21, yt21, zt21])
  63.         return data
  64.     # sun's coordination
  65.     x0 = 0
  66.     y0 = 0
  67.     z0 = 0
  68.     # 地球轨道
  69.     x1 = x0 + r1 * np.cos(omega1 * t_range)
  70.     y1 = y0 + r1 * np.sin(omega1 * t_range)
  71.     z1 = z0 + np.zeros(t_len)

  72.     # 月球轨道
  73.     x2 = x1 + r2 * np.sin(omega2 * t_range)
  74.     y2 = y1 + r2 * np.cos(omega2 * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
  75.     z2 = z1 + (y2 - y1) * np.tan(phi)

  76.     f = plt.figure(figsize=(6, 6))  # 绘图的画布
  77.     ax = f.add_subplot(111, projection='3d')  # 设置3d坐标系
  78.     ax.set_title("Sun-Earth-Moon Model")  # 设置图像标题(太阳-地球-月亮转动模型)

  79.     ax.plot([0], [0], [0], marker='o', color='red', markersize=16)  # 绘制太阳的各种属性
  80.     ax.plot(x1, y1, z1, 'r')  # 绘制地球图像
  81.     ax.plot(x2, y2, z2, 'b')  # 绘制月球图像
  82.     ax.set_xlim([-(r1 + 2), (r1 + 2)])  # 太阳用动模型在坐标系中的范围
  83.     ax.set_ylim([-(r1 + 2), (r1 + 2)])  # 地球用动模型在坐标系中的范围
  84.     ax.set_zlim([-5, 5])  # 月球用动模型在坐标系中的范围

  85.     # 红色球体代表太阳,蓝色球体代表地球,橙色球体代表月亮
  86.     line1, = ax.plot([], [], [], marker='o', color='blue', markersize=8, animated=True)
  87.     line2, = ax.plot([], [], [], marker='o', color='orange', markersize=4, animated=True)
  88.     line3, = ax.plot([], [], [], color='purple', animated=True)

  89.     # 将上述函数对象传如animmation.FuncAnimation函数以生成连读的地球运动模型
  90.     ani = animmation.FuncAnimation(f, update, frames=data_gen(), init_func=init, interval=20)

  91.     plt.show()


  92. #def Exercise():      # 定义演习函数
  93. #def Assessment():    #定义考核函数

  94. # 创建窗口
  95. app = Tk()

  96. # 定义窗口标题
  97. app.title("用Tkinter模块创建软件框架")

  98. # 设置长宽       这里的x是小写的,有点类似于乘号    宽 x 高
  99. app.geometry("800x800")

  100. # 定义窗口内容为theLabel
  101. theLabel = Label(app,  text="毕设草稿:气象部门工作方案", font="楷体 15", fg="green")
  102. # grid就是定位,网格式布局
  103. theLabel.grid()

  104. # 添加按钮
  105. # command 是点击按钮之后触发的事件
  106. button1 = Button(app, text="内容介绍", width=10, height=3)
  107. button1.grid(row=8, column=0, sticky=E)

  108. button2 = Button(app, text="仿真模型", width=10, height=3,command=Simulation)
  109. button2.grid(row=10, column=0, sticky=E)

  110. button3 = Button(app, text="实战演练", width=10, height=3)
  111. button3.grid(row=12, column=0, sticky=E)

  112. button4 = Button(app, text="进入考核", width=10, height=3)
  113. button4.grid(row=14, column=0, sticky=E)

  114. app.mainloop()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-25 11:18:14 | 显示全部楼层    本楼为最佳答案   
t_dlen在你的程序中出现了四次,都在函数Simulation 中,
第一次出现是在init函数中,直接出现在了右侧,这里尚未定义该变量,而且在你所封装的函数Simulation 外也没有定义过这个变量
第二次和第三次都是出现在global关键字之后,但是并没有这个名为t_dlen的全局变量
第四次才是出现在赋值操作符左侧,相当于定义了一个Simulation 函数内的局部变量。

你把这些变量的定义拉到Simulation 的前端,将那些函数向后放。
还有就是将那两个global改为nonlocal
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-25 12:44:30 | 显示全部楼层

我先前也是这样,把定义拉到前面,调试还是同样的报错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-25 12:50:24 | 显示全部楼层
sunrise085 发表于 2020-3-25 11:18
t_dlen在你的程序中出现了四次,都在函数Simulation 中,
第一次出现是在init函数中,直接出现在了右侧, ...

我把三个global改成了nonlocal
其他定义都没变
成功了!
但是不知道什么原理
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 03:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表