[Tutor] Critique of program

Bill Burns billburns at pennswoods.net
Wed Nov 17 04:31:45 CET 2004


I've written the program below and I'm wondering if anyone would be
interested in taking a look at it for me? I'd like to know if I'm doing
"things" correctly. I'm not a programmer. I found python several months
ago and just started tooling around with it and I've not stopped yet :-)

AFAIK, everything works correctly. The program does not error and the output 
is as expected. I'm just looking for tips on how I can improve it or for
feedback if I've done something silly that should be done differently.

I've only run this program on my Linux box so I have no idea if it works
on Windows, sorry. I built the program using Qt Designer, PyQt and pyuic 
(to compile the interface). I haven't included the GUI file, I decided to drop
it because my first post bounced (it was too big). I can supply the file if
someone wants it or if it's necessary.
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.

Also, I've commented out the report() function in my code. It's a work in

I appriecate your feedback!!


Bill Burns

#! /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.buttonPrint,SIGNAL("clicked()"), self.report)
       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 &)"),
                   validator=QIntValidator(0.00, 9999999.00, w)
    def report(self):
        """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
        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)
        total = add(stack)
    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):

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()

More information about the Tutor mailing list