2
\$\begingroup\$

While teaching myself Wx using this GridSizerTutorial page, I suddenly realized that there was a construct in Python that would let me considerably shorten the initialization code below. The three lines at the top replace the twelve commented lines below. (Three statements now split over six lines for greater clarity).

The question, should one do things this way? Is it Pythonic and DRY, or is it obscuring the function? I've encountered similar initializations in the past where the number groups of similar objects being initialized is considerably greater than four. The objects may later diverge, following "customization" calls to their setter methods.

inputOneIco,inputTwoIco,inputThreeIco,inputFourIco = [ 
    wx.StaticBitmap(self.panel, wx.ID_ANY, bmp) for _ in range(4) ]
labelOne, labelTwo, labelThree, labelFour          = [ 
    wx.StaticText(  self.panel, wx.ID_ANY, txt ) for txt in ('Name','Address','Email','Phone') ]
inputTxtOne,inputTxtTwo,inputTxtThree,inputTxtFour = [ 
    wx.TextCtrl(    self.panel, wx.ID_ANY, '') for _ in range(4) ]

#inputOneIco = wx.StaticBitmap(self.panel, wx.ID_ANY, bmp)
#labelOne = wx.StaticText(self.panel, wx.ID_ANY, 'Name')
#inputTxtOne = wx.TextCtrl(self.panel, wx.ID_ANY, '')

#inputTwoIco = wx.StaticBitmap(self.panel, wx.ID_ANY, bmp)
#labelTwo = wx.StaticText(self.panel, wx.ID_ANY, 'Address')
#inputTxtTwo = wx.TextCtrl(self.panel, wx.ID_ANY,'')

#inputThreeIco = wx.StaticBitmap(self.panel, wx.ID_ANY, bmp)
#labelThree = wx.StaticText(self.panel, wx.ID_ANY, 'Email')
#inputTxtThree = wx.TextCtrl(self.panel, wx.ID_ANY, '')

#inputFourIco = wx.StaticBitmap(self.panel, wx.ID_ANY, bmp)
#labelFour = wx.StaticText(self.panel, wx.ID_ANY, 'Phone')
#inputTxtFour = wx.TextCtrl(self.panel, wx.ID_ANY, '')
\$\endgroup\$
0
\$\begingroup\$

Personally, I don't think this is too bad. What would be better, though, is to keep them as lists:

icons = [wx.StaticBitmap(self.panel, wx.ID_ANY, bmp) for _ in range(4)]
labels = [wx.StaticText(self.panel, wx.ID_ANY, txt ) for txt in 
         ('Name', 'Address', 'Email', 'Phone')]
texts = [wx.TextCtrl(self.panel, wx.ID_ANY, '') for _ in range(4)]

This way you can later do stuff like:

for icon, label, text in zip(icons, labels, texts):
    do_stuff()

Note that I renamed you variables with lower_case as recommended by PEP8, Python's official style-guide, removed unnecessary whitespace and limited the line width to 80 characters.

If all three things describe a single object, why not make it an actual object? Add another class:

class Button():
    def __init__(self, panel, label, bmp):
        self.icon = wx.StaticBitmap(panel, wx.ID_ANY, bmp)
        self.label = wx.StaticText(panel, wx.ID_ANY, txt)
        self.text = wx.TextCtrl(panel, wx.ID_ANY, '')

bmp = None  # Seems to be defined elsewhere in your code
labels = ('Name', 'Address', 'Email', 'Phone')
buttons = [Button(self.panel, label, bmp) for label in labels]

Or maybe a namedtuple is sufficient here, even though the class is able to hide more complexity:

from collections import namedtuple

Button = namedtuple("Button", "icon label control")

bmp = None  # Seems to be defined elsewhere in your code
names = ('Name', 'Address', 'Email', 'Phone')

buttons = [Button(wx.StaticBitmap(self.panel, wx.ID_ANY, bmp),
                  wx.StaticText(self.panel, wx.ID_ANY, txt),
                  wx.TextCtrl(self.self.panel, wx.ID_ANY, '')
                  ) for txt in names]

Then, both for the class and the namedtuple, you can do stuff like:

for button in buttons:
    print button.label
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.