使效率稍高的函数结构

时间:2018-01-25 23:40:27

标签: python python-3.x user-interface kivy

我有一堆灯我试图控制。而不是每个按钮状态更改调用一个独特的函数,我想尝试并具有多功能函数,因为这是什么功能(据我所知)。

按钮调用功能:

    ToggleButton:
        id: KitchenSpot1Toggle
        text: "Kitchen Spot 1"
        on_press: root.changeKS1(1)

功能:

def changeKS1(self,change):
        if change==1 and b.get_light(1, 'on'):
            self.KitchenSpot1(False)
        else:
            self.KitchenSpot1(True)

该函数然后调用此函数以使用第三方库来物理地改变灯的状态。

    def KitchenSpot1(self,state):
        lights[0].name
        lights[0].on = state

我通过的原因" 1"功能内部是因为它不喜欢没有任何东西传递(我不知道它为什么不喜欢它)。如果你还没有猜到,我就是新手。我有一点cpp微控制器背景,但我试图了解python和基于PC的编程。我正在寻找一些关于如何最好地压缩这一点并使其尽可能高效的建议。我可能对python不太了解,但是,我知道我不应该在30次内输入几乎相同的东西。

提前感谢任何能分享他们智慧的人。

注意到我正在使用kivy和python来生成按钮。

完整的main.py代码:

from kivy.properties import StringProperty
import kivy
from kivy.uix.togglebutton import ToggleButton
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.app import App
kivy.require('1.10.0')
from phue import Bridge
import nest
b = Bridge('xx.xxx.xxx.xxx')
b.connect()
b.get_api()
lights = b.lights

class Controller(GridLayout):
    state = StringProperty('down')

    def __init__(self, **kwargs):
        super(Controller, self).__init__(**kwargs)
        Clock.schedule_interval(self.update, 1.0 / 60.0)

    def KitchenSpot1(self,state):
        lights[0].name
        lights[0].on = state

    def changeKS1(self,change):
        if change==1 and b.get_light(1, 'on'):
            self.KitchenSpot1(False)
        else:
            self.KitchenSpot1(True)


    def KitchenSpot2(self,state):
        lights[1].name
        lights[1].on = state

    def KitchenSpot3(self,state):
        lights[2].name
        lights[2].on = state

    def OfficeSpot1(self,state):
        lights[3].name
        lights[3].on = state

    def OfficeSpot2(self,state):
        lights[4].name
        lights[4].on = state

    def OfficeSpot3(self,state):
        lights[5].name
        lights[5].on = state

    def OfficeSpot4(self,state):
        lights[6].name
        lights[6].on = state

    def JuliaBedside(self,state):
        lights[7].name
        lights[7].on = state

    def JohnBedside(self,state):
        lights[8].name
        lights[8].on = state





    def update(self, dt):
        if b.get_light(1, 'on'):
            self.state = 'down'
         else:
            self.state = 'normal'


class ActionApp(App):
    def build(self):
        return Controller()


if __name__ == "__main__":
    myApp = ActionApp()
    myApp.run()

完整的action.kv代码

<Controller>:
    cols: 4
    rows: 3
    spacing: 10
    state: "normal"                                      

    ToggleButton:
        id: KitchenSpot1Toggle
        text: "Kitchen Spot 1"
        on_press: root.changeKS1(1)

        #on_release: root.KitchenSpot1(False)
        #state1 = app.update.h
        state: root.state


    ToggleButton:
        text: "Kitchen Spot 2"

    Button:
        text: "Kitchen Spot 3"

    Button:
        text: "Kitchen Spot 4"

    Button:
        text: "Office Spot 1"

    Button:
        text: "Office Spot 2"

    Button:
        text: "Office Spot 3"

    Button:
        text: "Office Spot 4"

更新: Python程序:

    def lightcontrol(self,lightnumber):
        if b.get_light(1, 'on'):
            lights[lightnumber].name
            lights[lightnumber].on (False)
            #self.KitchenSpot1(False)
        else:
            lights[lightnumber].name
            lights[lightnumber].on (True)
            #self.KitchenSpot1(True)

Kivy按钮:

    ToggleButton:
        id: KitchenSpot1Toggle
        text: "Kitchen Spot 1"
        on_press: root.lightcontrol(0)

2 个答案:

答案 0 :(得分:1)

让每个按钮调用相同的功能,但使用不同的参数。

# Add the a number parameter here based on what you've
def KitchenSpot(self,state, light_index):
    lights[light_index].name
    lights[light_index].on = state

然后在KV文件中

Button:
    text: "Kitchen Spot 3"
    on_press: root.KitchenSpot(state, light_index = 3)

Button:
    text: "Kitchen Spot 4"
    on_press: root.KitchenSpot(state, light_index = 4)

您只需要创建一个函数,每个按钮都会传入相关的light_index编号。

答案 1 :(得分:0)

既不知道kivy也不知道我已经尝试通过抽象方法的定义(以及创建action.kv文件)来减少代码冗余问题。

所以我希望你能找到这个:首先,我将在全局变量中定义按钮的所有相关数据,如:

BUTTONS = [
    {'id': 0, 'methodname': 'KitchenSpot1', 'text': 'Kitchen Spot 1'},
    {'id': 1, 'methodname': 'KitchenSpot2', 'text': 'Kitchen Spot 2'},
    ...
]

然后使用所有独特方法定义您的Controller类,就像您所做的那样(__init__update;但是我不知道应该做什么更新,我只是把它留下来定):

class Controller(GridLayout):
    state = StringProperty('down')
    def __init__(self, **kwargs):
        super(Controller, self).__init__(**kwargs)
        Clock.schedule_interval(self.update, 1.0 / 60.0)
    def update(self, dt):
        if b.get_light(1, 'on'):
            self.state = 'down'
         else:
            self.state = 'normal'

# this iteratively creates your button-individual methods
for button_dict in BUTTONS:        
    def func(self, state):
        lights[button_dict['id']].name   # whatever this might do just adressing the name attribute. Is it a python-property on lights that does some action?
        lights[button_dict['id']].on = state

    def func_change(self, change):
        if change == True and b.get_light(button_dict['id'], 'on'):
            getattr(self, button_dict['methodname'])(False)
        else:
            getattr(self, button_dict['methodname'])(True)

    # create .KitchenSpot1, .KitchenSpot2, ...
    setattr(Controller, button_dict['methodname'], func)
    # create .changeKitchenSpot1, .changeKitchenSpot2, ...
    setattr(Controller, "change{}".format(button_dict['methodname']), func_change)

实例化的Controller将根据所有方法名和change-methodnames命名绑定方法。

最后,您可以动态创建action.kv文件

actionkv_toggle_button = """    
    ToggleButton:
        id: {methodname}Toggle
        text: "{text}"
        on_press: root.change{methodname}(1)

        #on_release: root.{methodname}(False)
        #state1 = app.update.h
        state: root.state
"""

actionkv_str = """
<Controller>:
    cols: 4
    rows: 3
    spacing: 10
    state: "normal"

{buttons}
""".format(
    buttons="".join([
        actionkv_toggle_button.format(
            methodname=button_dict['methodname'],
            text=button_dict['text']
        ) for button_dict in BUTTONS
    ])
)

这给出了输出

<Controller>:
    cols: 4
    rows: 3
    spacing: 10
    state: "normal"


    ToggleButton:
        id: KitchenSpot1Toggle
        text: "Kitchen Spot 1"
        on_press: root.changeKitchenSpot1(1)

        #on_release: root.KitchenSpot1(False)
        #state1 = app.update.h
        state: root.state

    ToggleButton:
        id: KitchenSpot2Toggle
        text: "Kitchen Spot 2"
        on_press: root.changeKitchenSpot2(1)

        #on_release: root.KitchenSpot2(False)
        #state1 = app.update.h
        state: root.state

将其保存到文件

with open('action.kv', 'w') as f:
    f.write(actionkv_str)

有用的链接:

Dynamically attaching methods to a class

String formatting in python

List comprehension