Search code examples
pythondeclare

Python loop for multi statement


Simple declare in python is like.

x = 1
y = 1
z = 1

make it easier...

x,y,z = [1] * 3

but for function "statement"...

    import wx
    self.Bind(wx.EVT_MENU, self.exc11, id=exc11id)
    self.Bind(wx.EVT_MENU, self.exc15, id=exc15id)
    self.Bind(wx.EVT_MENU, self.exc37, id=exc37id)
    self.Bind(wx.EVT_MENU, self.exc55, id=exc55id)
    self.Bind(wx.EVT_MENU, self.exc88, id=exc88id)
    self.Bind(wx.EVT_MENU, self.exc99, id=exc99id)
    self.Bind(wx.EVT_MENU, self.rexc11, id=rexc11id)
    self.Bind(wx.EVT_MENU, self.rexc15, id=rexc15id)
    self.Bind(wx.EVT_MENU, self.rexc37, id=rexc37id)
    self.Bind(wx.EVT_MENU, self.rexc55, id=rexc55id)
    self.Bind(wx.EVT_MENU, self.rexc88, id=rexc88id)
    self.Bind(wx.EVT_MENU, self.rexc99, id=rexc99id)
    self.Bind(wx.EVT_MENU, self.excel11, id=excel11id)
    self.Bind(wx.EVT_MENU, self.excel15, id=excel15id)
    self.Bind(wx.EVT_MENU, self.excel37, id=excel37id)
    self.Bind(wx.EVT_MENU, self.excel55, id=excel55id)
    self.Bind(wx.EVT_MENU, self.excel88, id=excel88id)
    self.Bind(wx.EVT_MENU, self.excel99, id=excel99id)
    self.Bind(wx.EVT_MENU, self.calc, id=calcid)
    self.Bind(wx.EVT_MENU, self.edit, id=editid)
    self.Bind(wx.EVT_MENU, self.next, id=nextid)
    self.Bind(wx.EVT_MENU, self.prev, id=previd)

Why can I just use loop for multi-declare? e.g

for x in "exc11 exc15 exc37 exc55 exc88 exc99".split():
    xid = x + "id"
    self.Bind(wx.EVT_MENU, self.x, id=x)
...

Solution

  • ns = vars()
    for x in "exc11 exc15 exc37 exc55 exc88 exc99".split():
        xid = x + "id"
        self.Bind(wx.EVT_MENU, getattr(self, x), id=ns[xid])
    

    Whenever variable names contain numbers it is usually a sign that you should be using a list, tuple or dict instead of multiple variable. Use a list or tuple if the order of the variables is important, otherwise a dict may be more appropriate. Use a list if it the number of values is mutable, use a tuple otherwise.

    For example, instead of variables

    exc11id exc15id exc37id exc55id exc88id exc99id

    you could use a dict:

    excid = {'11': ..., '15': ..., }
    

    and similarly instead of having lots of attributes, you could have a single attribute self.exc which is a dict:

    self.exc = {'11': ..., '15': ..., }
    

    If you make this change, then the code could be simplified to

    for x in "11 15 37 55 88 99".split():
        self.Bind(wx.EVT_MENU, self.exc[x], id=excid[x])
    

    The reason why

    for x in "exc11 exc15 exc37 exc55 exc88 exc99".split():
        xid = x + "id"
        self.Bind(wx.EVT_MENU, self.x, id=x)
    

    does not work is because the values referenced by x and xid are strs. When you write self.x Python is looking for an attribute whose name is x, not an attribute whose name is the value referenced by the variable x. Instead, getattr(self, x) is the function call you are looking for.

    Similarly, xid is just a string. To get the value referenced by the variable whose name is the same as the value of that string, you need to look up the value in the vars() or globals() namespace.