Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

string or float comparison errors 2

Status
Not open for further replies.

plip1978

Technical User
Aug 22, 2007
29
GB
Hi,
I have a piece of code that performs the same test. It is a method inside a class:
Python:
  def setAngleA(self, newAngA):                 # set the gantry angle for that control point.
        if newAngA< 0 or newAngA> 360:
            print newAngA+ ' is not a valid angle.'
        else:
            self.__AngA = newAngA

I have another method for AngB that performs the same comparative test. However, method AngleA only works if I pass a string into it:
Python:
 test.setAngleA(str(Data[i][0]))
and AngB only works if I pass float data into it:
Python:
 test.setAngleB(float(Data[i][1]))

However, the 'if newAngA< 0 or newAngA> 360:' statement is the same (except for the newAngA newAngB local variable). Can anyone suggest why this might be the case? Could it be to do with passing by value? The data is created from a csv file which I read and convert to a list.
Python:
def readPlanDataFromCSV(filename):      #  , rowNum, columnNum): #columnStart = '', columnEnd = ''):
    import csv

    tempFile = open(filename, "rb")
    reader = csv.reader(tempFile)

    planList = []
    for row in reader:
        planList.append(row)
    return planList

    tempFile.close()

Thanks in advance!
 
I see no reason for this error but I do have a couple of observations

1) why 3 functions that perform the same task, all be it on desperate variables?
cannot this be re factored to use the same method for all variables?

2) be careful when comparing floats due to the inherent inaccuracies ( + should than not be >=360 as 360 deg would equal 0 deg)

3) reading each line in the CSV & appending to a list is inefficient a list comprehension would suffice planlist= [x for x in reader()]
but as I am sure you then loop over this list elsewhere in your code even that would be poor design & you would probably be better to return reader directly.


A Maintenance contract is essential, not a Luxury.
Do things on the cheap & it will cost you dear
 
Thanks for the reply IPGuru!

I use the two functions because they set different properties of the class. I want to set angles to two different items on a machine, so I've used two functions that (not in the example above, but in my actual class) are appropriately named. I realise that I could use just one method, but they I would still have to pass in an argument to specify which part of the machine I'm setting the angle of. I suppose I could try this and see if I still get the same issue.

In this case 360 and 0 degrees are acceptable because the machine has limits that stop it rotating much further than these points, therefore 0 would indicate it is at the top and ready able to rotate clockwise, and 360 at the top, but able to rotate anticlockwise. I'd be happy to use a different type than float, but I need to be able to specify the rotation position to at least 1 decimal place.

Thanks for the comprehension code - I'm not all that used to Python yet, so I'm not used to writing like that! I've written it like that, rather than returning reader, because I want to be able to index the result - i.e. specify the row index and column index (see the Data[1] above) - this way I can loop over a column (which contains e.g. all the angles for machine item A). I could see how to read out rows from reader, but I couldn't see how to refer to a specific element within that row. Any help would be appreciated!

Thanks again!
 
I suspect the csv module is doing some interpretation for you that is unwarranted (I never use the module, myself). Try just reading the file as text (and not binary) and see what you get.
Code:
def readPlanDataFromCSV(filename):      
    tempFile = open(filename, "r")
    
    planList = []
    for row in tempFile:
        planList.append(row.split(','))
    return planList

    tempFile.close()

_________________
Bob Rashkin
 
actually, the return means you'll never get to the close, also best to remove linefeeds. So:
Code:
def readPlanDataFromCSV(filename):      
    tempFile = open(filename, "r")
    
    planList = []
    for row in tempFile:
        planList.append(row.split(',').strip('\n'))
    tempFile.close()
    return planList

_________________
Bob Rashkin
 
Thanks Bong!
However, I'm getting this error: 'AttributeError: 'list' object has no attribute 'strip''. I guess the row object is a list. Will this method return a two dimensional array that I can index like Data[j]?
Thanks,
Phil.
 
Thanks everyone for your help!

I've changed the method to this:
Python:
def readPlanDataFromCSV(filename):      #  , rowNum, columnNum): #columnStart = '', columnEnd = ''):
    import csv

    tempFile = open(filename, "rb")
    reader = list(csv.reader(tempFile))
    return reader

And realised that the reason one method was working as a string and the other was working as a float was that I had written them differently! I'd written the same comparison, but swapped around the error statement (before and after the else). I felt a bit stupid to say the least! However, it works now!
Thank you again for your help!
 
if the code is the same just the particular variables for machine settings changing then I would still consider the coad cleaner to pass the variable as one of the parameters for a number of reasons

1) the code has only to be written once
2) if it ever needs to change you only have to change it in one location which reduces the chances of introducing bugs.

For 2 items it is probably OK, but as soon as you find yourself writing the same code (or a close variant) for a 3rd time you should be considering re-factoring to a single function.


has numerous examples of code that clearly started out as simple send-offs but failed to follow the above advice soon enough resulting in an unmaintainable pile of spaghetti (Clean Version).

split will return a list row.split(',')[:1).strip('\n') would work but be platform specific (what about systems that end CR/LF?) this is one reason why the CSV module is usually a better option than rolling your own code.

This code you would return a 2 dimensional list but a list comprehension is more efficient than multiple appends. It took me a little time to get my head around them but once it clicked it made a huge difference to my code.



A Maintenance contract is essential, not a Luxury.
Do things on the cheap & it will cost you dear
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top