Python - 无法一步一步地运行包含循环函数的函数

时间:2017-10-18 10:09:17

标签: python function loops

作为标题,我有问题使用多次运行包含循环函数的函数。最好的是我想要的。我尝试通过列表解决它,例如Funs_list = [measure(“A”),measure(“B”)],但结果相同。循环函数不会每次都一步一步地运行。

from Tkinter import *
import time

def measure(name):
    global voltage, data

    data = []
    if name == "A":
        voltage = -0.2
        limits = +0.2
    else:
        voltage = -0.1
        limits = +0.1
    def loop():
            global voltage , data
            data.append(round(voltage,3))

            voltage += 0.02

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))
                root.after_cancel(loop)
                print 'data', data

            else:
                root.after(1000, loop)
    root.after(1, loop)



def others():
    global data

    measure("A")
    A = data
    print 'A', A


    measure("B")
    B = data
    print 'B', B

    print 'i am here'



root = Tk()
root.title("A Tool")
Button(root, text="Test other",width=38, height = 8, bg='gray',command=lambda:others()).pack()

root.mainloop()

当我按下'其他人'按钮时,结果如下:

    A []
    B []
    i am here
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0, 0.0, 0.0]

但我希望得到如下结果,逐步完成“其他”功能。我该怎么办?

    data [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    A [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    B [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    i am here

2 个答案:

答案 0 :(得分:0)

我不是Tkinter的专家,但问题是root.after()使用不当。

您的函数measure()已经返回并打印了A,但由于root.after()尚未被调用,因为它必须等待几毫秒,因此您将获得空表。然后在ms传递之后,您的数据会更新,但是您希望完成的工作已经结束了。

我稍微改变了你的代码:

def measure(name):
    ...
    def loop():
            ...

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))

                print ('data', data)
                return  # root.after_cancel(loop)

            else:
                loop()  # root.after(1, loop)

    loop()  # root.after(1, loop)

这是我的结果:

data [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0] A [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0]

答案 1 :(得分:0)

如果我正确理解了问题,看起来您不希望measure返回,直到循环运行完毕。如果是这种情况,您可以使用tkinter在继续之前等待变量设置的能力。

您可以尝试修改代码,使其如下所示:

def measure(name):
    flag = BooleanVar()
    ...
    def loop():
        ...
        if voltage > -0.01:
            ...
            print 'data', data
            flag.set(True)
        ...
    loop()
    root.wait_variable(1000, loop)

使用上述内容,measure将不会返回,直到设置了标志,并且在循环完成之前不会设置该标志。

基于事件的解决方案

但我个人不会这样做。你想要做的似乎就是“当电压超过阈值时做一些事情”。上升的电压可以被认为是另一个事件,就像点击按钮或键入一些文本一样。

如果是这种情况,您可能想要创建并绑定到虚拟事件

例如,您可能希望创建表示A和B电压上升的事件"<<Voltage-A>>""<<Voltage-B>>"。您可以绑定到这些事件,以便在它们发生时,您可以执行任何您需要执行的操作。此外,由于您只想在A上的电压上升后测量B,您可以在同一事件上触发B的测量。

这是一个基于原始代码的有点人为的例子:

from Tkinter import *

def measure(name):
    global voltage, data

    data = []

    if name == "A":
        voltage = -0.2
        limits = +0.2
    else:
        voltage = -0.1
        limits = +0.1
    def loop():
            global voltage , data
            data.append(round(voltage,3))

            voltage += 0.02

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))
                root.after_cancel(loop)
                event_name = "<<Voltage-%s>>" % name
                print 'data', data
                root.event_generate(event_name)

            else:
                root.after(1000, loop)

    loop()

def print_data(name):
    global data
    print name, data

root = Tk()
root.title("A Tool")
Button(root, text="Test other",width=38, height = 8, bg='gray',command=lambda:measure("A")).pack()

root.bind("<<Voltage-A>>", lambda event: (print_data("A"), measure('B')))
root.bind("<<Voltage-B>>", lambda event: print_data("B"))

root.mainloop()