Shark丶 发表于 2020-3-25 10:57:03

关于调用函数报错未定义

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


#def Introduction():# 定义简介

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

    import matplotlib.animation as animmation

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

    def update(data):
      # 随时间t变换设置新的地球位置的坐标,也即是随animmation.FuncAnimation函数的帧数参数变化每一帧的不同坐标位置的图片对象参数
      global line1, line2, line3
      line1.set_data(, data])
      line1.set_3d_properties(data)
      line2.set_data(, data])
      line2.set_3d_properties(data)
      line3.set_data(, data])
      line3.set_3d_properties(data)
      return line1, line2, line3,

    def init():# 地球的起始位置
      global line1, line2, line3
      ti = 0
      t = t_drange
      xt1 = x0 + r1 * np.cos(omega1 * t)
      yt1 = y0 + r1 * np.sin(omega1 * t)
      zt1 = z0 + 0
      xt2 = xt1 + r2 * np.sin(omega2 * t)
      yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
      zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
      xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
      yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
      zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
      line1, = ax.plot(, , , marker='o', color='blue', markersize=8)
      line2, = ax.plot(, , , marker='o', color='orange', markersize=4)
      line3, = ax.plot(xt21, yt21, zt21, color='purple')
      return line1, line2, line3

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

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

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

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

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

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

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

    plt.show()


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

# 创建窗口
app = Tk()

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

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

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

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

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

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

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

app.mainloop()

永恒的蓝色梦想 发表于 2020-3-25 11:09:24

试试这样from tkinter import *
from tkinter import messagebox
import os
import tkinter as tk


#def Introduction():# 定义简介

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

    import matplotlib.animation as animmation

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

    def update(data):
      # 随时间t变换设置新的地球位置的坐标,也即是随animmation.FuncAnimation函数的帧数参数变化每一帧的不同坐标位置的图片对象参数
      global line1, line2, line3
      line1.set_data(, data])
      line1.set_3d_properties(data)
      line2.set_data(, data])
      line2.set_3d_properties(data)
      line3.set_data(, data])
      line3.set_3d_properties(data)
      return line1, line2, line3,

    def init():# 地球的起始位置
      global line1, line2, line3
      ti = 0
      t = t_drange
      xt1 = x0 + r1 * np.cos(omega1 * t)
      yt1 = y0 + r1 * np.sin(omega1 * t)
      zt1 = z0 + 0
      xt2 = xt1 + r2 * np.sin(omega2 * t)
      yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
      zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
      xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
      yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
      zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
      line1, = ax.plot(, , , marker='o', color='blue', markersize=8)
      line2, = ax.plot(, , , marker='o', color='orange', markersize=4)
      line3, = ax.plot(xt21, yt21, zt21, color='purple')
      return line1, line2, line3

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

    def data_gen():# 随时间t变换的地球和月球坐标,也即是animmation.FuncAnimation函数的帧数参数
      global x0, y0, z0, t_dlen
      data = []
      for ti in range(1, t_dlen):
            t = t_drange
            xt1 = x0 + r1 * np.cos(omega1 * t)
            yt1 = y0 + r1 * np.sin(omega1 * t)
            zt1 = z0
            xt2 = xt1 + r2 * np.sin(omega2 * t)
            yt2 = yt1 + r2 * np.cos(omega2 * t) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
            zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
            xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
            yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range) / (np.cos(phi) * (1 + np.tan(phi) ** 2))
            zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
            data.append()
      return data
    # sun's coordination
    x0 = 0
    y0 = 0
    z0 = 0
    # 地球轨道
    x1 = x0 + r1 * np.cos(omega1 * t_range)
    y1 = y0 + r1 * np.sin(omega1 * t_range)
    z1 = z0 + np.zeros(t_len)

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

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

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

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

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

    plt.show()


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

# 创建窗口
app = Tk()

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

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

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

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

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

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

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

app.mainloop()

sunrise085 发表于 2020-3-25 11:18:14

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

你把这些变量的定义拉到Simulation 的前端,将那些函数向后放。
还有就是将那两个global改为nonlocal

Shark丶 发表于 2020-3-25 12:44:30

永恒的蓝色梦想 发表于 2020-3-25 11:09
试试这样

我先前也是这样,把定义拉到前面,调试还是同样的报错

Shark丶 发表于 2020-3-25 12:50:24

sunrise085 发表于 2020-3-25 11:18
t_dlen在你的程序中出现了四次,都在函数Simulation 中,
第一次出现是在init函数中,直接出现在了右侧, ...

我把三个global改成了nonlocal
其他定义都没变
成功了!
但是不知道什么原理
页: [1]
查看完整版本: 关于调用函数报错未定义