[Tutor] Critique of program

Kent Johnson kent37 at tds.net
Thu Nov 18 12:08:45 CET 2004


Bill,

To me, it seems a little strange to be using introspection every time 
you want a list of all the lineEdits. I think it would be more 
straightforward to keep a list of all the lineEdits with their 
attributes and iterate the list. This would avoid searching through 
self.__dict__ and trying to figure out what is in it.

I'll try to sketch out this solution:

Start with a list of everything you need to know about a lineEdit. This 
includes ID, OD and maybe the label you use on the form -

pipes = [
     ( '1/2"', .622),
     ('3/4"', .824),
     ('1"',  1.049),
     # etc
]

You might divide this up into four pieces, one for each page.

Now create the forms based on data in the list, and while you do it 
create a new list (or maybe a dict, if you ever need access to a data 
about a specific lineEdit) that keeps a reference to the lineEdit and 
the data about it:

lineEdits = []
for od, id in pipes:
     lineEdit = ... # however you create this
     lineEdits.append( (lineEdit, od, id) )
     # or maybe lineEdits[lineEdit] = (od, id) for a dict

Now you calc loop looks like this:

         for w, od, id in lineEdits:
             length = w.displayText()
             if length:    # Note: this is same as if not length == ""
                length = int(length)  # No need for str or 10
                x = volCalc(id, length)
                stack.append(x)

and the clear loop is just

         for w, od, id in lineEdits:
             w.clear()

Kent

Bill Burns wrote:
> You will see in the code below there are several places where I have
> replaced the line "if isinstance():" with "if hasattr():". After reading some
> posts on c.l.p, I got the feeling that it is better to use hasattr() instead 
> of isinstance(). Is this correct?? You can find the posts I'm talking about
> by "googling" c.l.p for the phrase "isinstance considered harmful". 
> Either way, I'm not really trying to check whether the object has a certain
> attribute that I desire, I just want to know if it's the object that I'm
> looking for. IOW, are you a lineEdit or are you a button, if you're a button
> then go away I only like lineEdits ;-) The code seems to work no matter which
> function I use.

> <CODE>
> #! /usr/bin/env python
> 
> """
> Pipe Volume Calc - calculates the water volume (in U.S. gallons) contained
> inside various types and sizes of pipe.
> 
> The user selects a type of pipe, a size of pipe and then enters a length (in
> feet). Water volume is automatically calculated and displayed as the data is
> entered into the form.
> 
> There's a GUI front-end which is separate from this module. I made the GUI
> using Qt Designer, PyQt and pyuic. The GUI is a tabbed dialog containing 
> multiple lineEdits. Each lineEdit corresponds to a specific size of pipe, 
> i.e., 1/2", 3/4", etc. Each tabbed page corresponds to a different type of 
> pipe (steel, copper or PVC). The user selects the page containing the type 
> of pipe and then enters the total footage.
> 
> The first dictionary below (pipeDict) holds all the inside diameters (in 
> inches) for the various pipes. The inside diameter (and length) are needed 
> to calculate water volume.
> 
> The lineEdit "groups" are broken out as follows:                                                             
>     
> lineEdit1   -> lineEdit25   (standard steel pipe)        
> lineEdit1_1 -> lineEdit25_1 (extra strong steel pipe)     
> lineEdit1_2 -> lineEdit15_2 (type L copper pipe)       
> lineEdit1_3 -> lineEdit13_3 (schedule 40 PVC pipe)       
> lineEdit1_4 -> lineEdit13_4 (schedule 80 PVC pipe)
> """
>     
> pipeDict = \
> {'lineEdit1': .622, 'lineEdit2': .824, 'lineEdit3': 1.049, 
> 'lineEdit4': 1.38, 'lineEdit5': 1.61, 'lineEdit6': 2.067, 
> 'lineEdit7': 2.469, 'lineEdit8': 3.068, 'lineEdit9': 3.548, 
> 'lineEdit10': 4.026, 'lineEdit11': 5.047, 'lineEdit12': 6.065, 
> 'lineEdit13': 7.981, 'lineEdit14': 10.02, 'lineEdit15': 12.00, 
> 'lineEdit16': 13.25, 'lineEdit17': 15.25, 'lineEdit18': 17.25, 
> 'lineEdit19': 19.25, 'lineEdit20': 21.25, 'lineEdit21': 23.25, 
> 'lineEdit22': 29.25, 'lineEdit23': 35.25, 'lineEdit24': 41.25, 
> 'lineEdit25': 47.25, 
> 
> 'lineEdit1_1': .546, 'lineEdit2_1': .742, 'lineEdit3_1': .957, 
> 'lineEdit4_1': 1.278, 'lineEdit5_1': 1.50, 'lineEdit6_1': 1.939, 
> 'lineEdit7_1': 2.323, 'lineEdit8_1': 2.90, 'lineEdit9_1': 3.364, 
> 'lineEdit10_1': 3.826, 'lineEdit11_1': 4.813, 'lineEdit12_1': 5.761, 
> 'lineEdit13_1': 7.625, 'lineEdit14_1': 9.75, 'lineEdit15_1': 11.75, 
> 'lineEdit16_1': 13.00, 'lineEdit17_1': 15.00, 'lineEdit18_1': 17.00, 
> 'lineEdit19_1': 19.00, 'lineEdit20_1': 21.00, 'lineEdit21_1': 23.00, 
> 'lineEdit22_1': 29.00, 'lineEdit23_1': 35.00, 'lineEdit24_1': 41.00, 
> 'lineEdit25_1': 47.50, 
> 
> 'lineEdit1_2': .585, 'lineEdit2_2': .830, 'lineEdit3_2': 1.075, 
> 'lineEdit4_2': 1.32, 'lineEdit5_2': 1.565, 'lineEdit6_2': 2.055, 
> 'lineEdit7_2': 2.545, 'lineEdit8_2': 3.035, 'lineEdit9_2': 3.525, 
> 'lineEdit10_2': 4.015, 'lineEdit11_2': 5.00, 'lineEdit12_2': 5.985, 
> 'lineEdit13_2': 7.925, 'lineEdit14_2': 9.875, 'lineEdit15_2': 11.845,  
> 
> 'lineEdit1_3': .731, 'lineEdit2_3': .937, 'lineEdit3_3': 1.182, 
> 'lineEdit4_3': 1.52, 'lineEdit5_3': 1.755, 'lineEdit6_3': 2.221, 
> 'lineEdit7_3': 2.672, 'lineEdit8_3': 3.284, 'lineEdit9_3': 4.263, 
> 'lineEdit10_3': 6.345, 'lineEdit11_3': 8.303, 'lineEdit12_3': 10.385, 
> 'lineEdit13_3': 12.344, 
> 
> 'lineEdit1_4': .693, 'lineEdit2_4': .896, 'lineEdit3_4': 1.136, 
> 'lineEdit4_4': 1.469, 'lineEdit5_4': 1.70, 'lineEdit6_4': 2.157, 
> 'lineEdit7_4': 2.599, 'lineEdit8_4': 3.20, 'lineEdit9_4': 4.163, 
> 'lineEdit10_4': 6.193, 'lineEdit11_4': 8.125, 'lineEdit12_4': 10.157, 
> 'lineEdit13_4': 12.063}
> 
> """
> This dictionary (sizeDict) holds all of the pipe sizes. Each size
> corresponds to a matching lineEdit on the GUI. I'm thinking I may 
> use this dict to generate some kind of report. Something that the 
> user can print out or save. I don't know if this is the right 
> direction or not but I'll figure it out later!
> """
> 
> sizeDict = \
> {'lineEdit1': '1/2"', 'lineEdit2': '3/4"', 'lineEdit3': '1"', 
> 'lineEdit4': '1-1/4"', 'lineEdit5': '1-1/2"', 'lineEdit6': '2"', 
> 'lineEdit7': '2-1/2"', 'lineEdit8': '3"', 'lineEdit9': '3-1/2"', 
> 'lineEdit10': '4"', 'lineEdit11': '5"', 'lineEdit12': '6"', 
> 'lineEdit13': '8"', 'lineEdit14': '10"', 'lineEdit15': '12"', 
> 'lineEdit16': '14"', 'lineEdit17': '16"', 'lineEdit18': '18"', 
> 'lineEdit19': '20"', 'lineEdit20': '22"', 'lineEdit21': '24"', 
> 'lineEdit22': '30"', 'lineEdit23': '36"', 'lineEdit24': '42"', 
> 'lineEdit25': '48"', 
> 
> 'lineEdit1_1': '1/2"', 'lineEdit2_1': '3/4"', 'lineEdit3_1': '1"', 
> 'lineEdit4_1': '1-1/4"', 'lineEdit5_1': '1-1/2"', 'lineEdit6_1': '2"', 
> 'lineEdit7_1': '2-1/2"', 'lineEdit8_1': '3"', 'lineEdit9_1': '3-1/2"', 
> 'lineEdit10_1': '4"', 'lineEdit11_1': '5"', 'lineEdit12_1': '6"', 
> 'lineEdit13_1': '8"', 'lineEdit14_1': '10"', 'lineEdit15_1': '12"', 
> 'lineEdit16_1': '14"', 'lineEdit17_1': '16"', 'lineEdit18_1': '18"', 
> 'lineEdit19_1': '20"', 'lineEdit20_1': '22"', 'lineEdit21_1': '24"', 
> 'lineEdit22_1': '30"', 'lineEdit23_1': '36"', 'lineEdit24_1': '42"', 
> 'lineEdit25_1': '48"', 
> 
> 'lineEdit1_2': '1/2"', 'lineEdit2_2': '3/4"', 'lineEdit3_2': '1"', 
> 'lineEdit4_2': '1-1/4"', 'lineEdit5_2': '1-1/2"', 'lineEdit6_2': '2"', 
> 'lineEdit7_2': '2-1/2"', 'lineEdit8_2': '3"', 'lineEdit9_2': '3-1/2"', 
> 'lineEdit10_2': '4"', 'lineEdit11_2': '5"', 'lineEdit12_2': '6"', 
> 'lineEdit13_2': '8"', 'lineEdit14_2': '10"', 'lineEdit15_2': '12"',  
> 
> 'lineEdit1_3': '1/2"', 'lineEdit2_3': '3/4"', 'lineEdit3_3': '1"', 
> 'lineEdit4_3': '1-1/4"', 'lineEdit5_3': '1-1/2"', 'lineEdit6_3': '2"', 
> 'lineEdit7_3': '2-1/2"', 'lineEdit8_3': '3"', 'lineEdit9_3': '4"', 
> 'lineEdit10_3': '6"', 'lineEdit11_3': '8"', 'lineEdit12_3': '10"', 
> 'lineEdit13_3': '12"', 
> 
> 'lineEdit1_4': '1/2"', 'lineEdit2_4': '3/4"', 'lineEdit3_4': '1"', 
> 'lineEdit4_4': '1-1/4"', 'lineEdit5_4': '1-1/2"', 'lineEdit6_4': '2"', 
> 'lineEdit7_4': '2-1/2"', 'lineEdit8_4': '3"', 'lineEdit9_4': '4"', 
> 'lineEdit10_4': '6"', 'lineEdit11_4': '8"', 'lineEdit12_4': '10"', 
> 'lineEdit13_4': '12"'}
> 
> import sys
> import types
> from qt import *
> 
> from pipeCalcGUI import PipeForm
> 
> class PipeConnector(PipeForm):
>     def __init__(self, parent=None):
>        PipeForm.__init__(self, parent)
>        self.connect(self.buttonClear,SIGNAL("clicked()"), self.clearLineEdits)
>        self.connect(self.buttonExit,SIGNAL("clicked()"),self,SLOT("close()"))
>        self.connect(self.buttonPrint,SIGNAL("clicked()"), self.report)
>        self.lineEditTotal.setAlignment(QLineEdit.AlignRight)
>        
>        for name in self.__dict__:
>            w = getattr(self, name)
>            if name != "lineEditTotal":
>                if hasattr(w, "displayText"): # if isinstance(w, QLineEdit):
>                    self.connect(w,SIGNAL("textChanged(const QString &)"),
>                                 self.calc)
>                    w.setAlignment(QLineEdit.AlignRight)
>                    validator=QIntValidator(0.00, 9999999.00, w)
>                    w.setValidator(validator)
>                  
>     def report(self):
>         pass
>         """Maybe I can use some variation of this to build a dictionary
>            that contains the values from sizeDict and the lengths that
>            the user has entered. At some point in time, I'm going to want
>            a nicely formatted report or print out.
>         """
>         """
>         reportDict = {}
>         for name in self.__dict__:
>             w = getattr(self, name)
>             if name != "lineEditTotal":
>                 if hasattr(w, "displayText"): # if isinstance(w, QLineEdit):
>                     length = w.displayText()
>                     if not length == "":
>                        length = int(str(length),10)
>                        #size = sizeDict[name]
>                        #reportDict[size] = length
>                        reportDict[name] = length
>         print reportDict
>         """
> 
>     def calc(self):
>         """First I create an empty list, then iterate through all the objects
>            in self.__dict__, then "weed out" all of the objects / instances
>            that are NOT lineEdits, grab the text from each lineEdit, skipping 
>            any lineEdit with and empty string, pull an inside diameter for
>            each corresponding lineEdit from the dictionary, send that data
>            to volCalc() to calculate gallons in the pipe, pop each gallon
>            calculation on to the stack, send the data on the stack to add()
>            to be summed and finally, set lineEditTotal to display the total
>            gallons 
>         """
>         stack = []
>         for name in self.__dict__:
>             w = getattr(self, name)
>             if name != "lineEditTotal":
>                 if hasattr(w, "displayText"): #if isinstance(w, QLineEdit):
>                     length = w.displayText()
>                     if not length == "":
>                        length = int(str(length),10)
>                        ID = pipeDict[name]
>                        x = volCalc(ID, length)
>                        stack.append(x)
>         total = add(stack)
>         self.lineEditTotal.setText(total)
>   
>     def clearLineEdits(self):
>         """Clears the data in every lineEdit
>         """
>         for name in self.__dict__:
>             w = getattr(self, name)
>             if hasattr(w, "displayText"): # if isinstance(w, QLineEdit):
>                 w.clear()
>         self.lineEditTotal.setText("")
> 
> def volCalc(ID, length):
>     """ Calculates the water volume inside of the pipe
>     """
>     gal = ((ID*.5)**2)*3.14159265*(12*length)/(230.9429931) 
>     gal = "%0.2f" % gal
>     return gal
>     
> def add(args):
>     """Sums all of the values on the stack
>     """
>     sum = 0
>     for i in args:
>         i = float(i)
>         sum = sum + i
>     sum = str(sum)
>     return sum
> 
> if __name__ == "__main__":
>     app = QApplication(sys.argv)
>     QObject.connect(app, SIGNAL("lastWindowClosed()"),
>                     app, SLOT("quit()"))
>     win = PipeConnector()
>     app.setMainWidget(win)
>     win.show()
>     app.exec_loop()
> </CODE>
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 


More information about the Tutor mailing list