【问题标题】:Start multiple independent functions with a single global variable使用单个全局变量启动多个独立函数
【发布时间】:2018-11-26 01:33:02
【问题描述】:

我确定我想错了,但我不知道如何走出死胡同。

我正在构建一个基于外部输入独立闪烁 LED 的程序。我的代码适用于单个 LED。然而,我能想到的让它适用于多个 LED 的所有方法似乎都很愚蠢。

基本上,我希望函数的所有实例都以相同的全局变量开始,但是一旦它们开始烹饪,它们就会按照自己的方式进行。这是当前代码的相关部分:

counter = 0
time_from_start = 0
new_average = 0

#eventually this will be get_new_average(sensor_number)
def get_new_average():
    #average is going to be time in .... ms?
    #eventually it will be the average from the arduino
    new_average = int(input("new average? "))

def lighter_up(light_number, intensity):
    print("lighter_up intensity = " + str(intensity))
    #this line needs to be modified to whatever the intensity should be
    strip.setPixelColorRGB(light_number, intensity, 0, 0)
    strip.show()
    return intensity + 1

def lighter_down(light_number, intensity):
    print("lighter_down value = " + str(255 - (intensity - 255)))
    #this line needs to be modified to whatever the intensity should be
    strip.setPixelColorRGB(light_number, 255 - (intensity - 255), 0, 0)
    strip.show()
    return intensity + 1

def heartbeat(light):
    #acknowledge that counter is a global variable
    global counter
    global start_time

    if counter == 0:
        get_new_average()
        #this counts seconds from an arbitrary start point
        start_time = int(time.perf_counter())
        counter = 1
    #the 255 value is arbitrary
    #need to change it when you figure out the flash
    elif 0 < counter < 255:
        counter = lighter_up(light, counter)
    elif 254 < counter <510:
        counter = lighter_down(light, counter)
    elif counter > 509:
        #turn off the light
        strip.setPixelColorRGB(light, 0, 0, 0)
        strip.show()
        #difference between the start time and now
        time_from_start = int(time.perf_counter()) - start_time
        print(time_from_start)
        #if the time from the start of the flash is less than the
        #duration of the heartbeat, as defiend by new_average
        if time_from_start < new_average:
            #just wait it out
            pass
        #if the time from start has hit the new_average
        #it is time for a new heartbeat
        elif time_from_start >= new_average:
            counter = 0
        else:
            print("There was an error in heartbeat()")
    else:
        print("error: counter = " + str(counter))
while True:
    heartbeat(0)

我想在末尾添加一个heartbeat(1) 来控制最终将连接到第二个传感器的第二个灯。但是,这样做会使 heartbeat(0) 中的“计数器”和 heartbeat(1) 中的“计数器”发生冲突(并且对 time_from_start 和 new_average 产生相同的影响)。

我可以创建一个全局变量列表(“counter0”、“counter1”等),但这看起来既愚蠢又不优雅。我也可以在 heartbeat() 中移动计数器,但是每次循环时它都会重置为零,并且什么都不会发生。一定有更好的办法!

我强烈怀疑(希望?)这是一个完全常见的 python 东西,有一个非常明显的解决方案。我就是找不到。有什么想法吗?

谢谢

【问题讨论】:

    标签: python python-3.x loops variables global-variables


    【解决方案1】:

    如果我理解正确,您正在寻找的是一种为每个“灯”设置不同的变量集 countertime_from_startnew_average 的方法,这样您就可以将函数分别应用于每个灯没有函数覆盖其他“灯”自己的变量集?

    如果是,pythonic 的解决方案是定义一个类并为每个灯光创建一个实例。然后,您的函数将成为该类的方法,并且每个实例都有自己的状态(变量集):

    class Light(object):
        def __init__(self, number):
           self.number = number
           self.counter = 0
           self.time_from_start = 0
           self.new_average = 0
    
        def get_new_average(self):
            self.new_average = int(input("new average? "))
    
        def lighter_up(self, intensity):
            print("lighter_up intensity = " + str(intensity))
            #this line needs to be modified to whatever the intensity should be
            strip.setPixelColorRGB(self.number, intensity, 0, 0)
            strip.show()
            return intensity + 1
    
        def lighter_down(light_number, intensity):
            print("lighter_down value = " + str(255 - (intensity - 255)))
            #this line needs to be modified to whatever the intensity should be
            strip.setPixelColorRGB(self.number, 255 - (intensity - 255), 0, 0)
            strip.show()
            return intensity + 1
    
        def heartbeat(self):
            if self.counter == 0:
                self.get_new_average()
                #this counts seconds from an arbitrary start point
                start_time = int(time.perf_counter())
                self.counter = 1
    
            #the 255 value is arbitrary
            #need to change it when you figure out the flash
            elif 0 < self.counter < 255:
                self.counter = self.lighter_up(self.counter)
            elif 254 < self.counter <510:
                self.counter = self.lighter_down(self.counter)
            elif counter > 509:
                #turn off the light
                strip.setPixelColorRGB(light, 0, 0, 0)
                strip.show()
                #difference between the start time and now
                self.time_from_start = int(time.perf_counter()) - start_time
                print(self.time_from_start)
                #if the time from the start of the flash is less than the
                #duration of the heartbeat, as defiend by new_average
                if self.time_from_start < self.new_average:
                    #just wait it out
                    pass
                #if the time from start has hit the new_average
                #it is time for a new heartbeat
                elif self.time_from_start >= self.new_average:
                    self.counter = 0
                else:
                    print("There was an error in heartbeat()")
            else:
                print("error: counter = " + str(self.counter))
    
    
    lights = [Light(0), Light(1)]
    while True:
       for light in lights:
           light.heartbeat() 
    

    【讨论】:

    • 谢谢!我有一种刺痛的感觉,这是课程旨在解决的问题类型,但不太确定如何将其转化为行动。我想我的 python 世界变得更复杂了。
    • 其实你可以在没有类的情况下解决问题——使用{"counter":XXX, "new_average": XXX, "time_from_start": XXX} dicts 列表(而不是Light 实例列表)并将这些dicts 传递给你的函数(所以他们会使用@ 987654327@ 等而不是全局变量),但是是的,这是 一个 类旨在解决的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 2020-11-15
    • 1970-01-01
    • 2014-09-26
    • 2015-02-21
    • 2015-05-25
    相关资源
    最近更新 更多