Cameron,

Again, thanks for the help. I agree with everything you wrote, but... The code 
was thrown together to produce the error so I could illustrate the problem. It 
was by design junk. But it did produce the error, I got some great answers to 
my situation, so I am very grateful for the help.

Dave,
April 1, 2019 10:30 PM, "Cameron Simpson" <c...@cskk.id.au 
(mailto:c...@cskk.id.au)> wrote:
 On 01Apr2019 22:02, Dave <dbola...@offilive.com 
(mailto:dbola...@offilive.com)> wrote:
 As classes get more complex, it is good to call a function to do some >of the 
processing, and make
the code easier to follow. My question is >how to do that? I've attached some 
silly code to
illustrate the >point. The error is: name 'validScale' is not defined. Well, 
yes it >is, but maybe
not the correct way. Suggestions? 

It is and it isn't. See below:
 class TempConverter():
""" Temperature Converter converts a tempeature from one scale
to another scale. For example: 32, F, C will return
0 degrees C
""" 

[...]
 def validScale(self, scaleName):
if scaleName.upper == 'F' or 'C' or 'K':
return True
else:
return False

def convertTemp(self):
""" Converts temperature scale if scales valid."""
if validScale(self.scale):
scaleValid = True 

[...]

It is an instance method, so:

if self.validScale(self.scale)

would resolve the name. However, there are several things worth discussing here.

First up, validScale itself returns a Boolean, so just return the test result. 
Change:

if scaleName.upper == 'F' or 'C' or 'K':
return True
else:
return False

into:

return scaleName.upper == 'F' or 'C' or 'K'

Second, the condition is buggy. You want this:

return scaleName.upper() in ('F', 'C', 'K')

i.e. you need to call (the "()") the .upper method, and you need to check if 
the result is in your
collection of valid results.

This expression:

value == A or B or C

means: True if value == A, otherwise B if B is true, otherwise C.

The next thing to observe is that you're testing whether self.scale is valid. 
Normal practice would
be to make that test in __init__, and raise a ValueError if it is not so:

def __init__(self, .....scale...):
if scale.upper() not in ('F', 'C', 'K'):
raise ValueError("invalid scale %r: expected one of F, C or K" % (scale,))
why recite the scale in the message? Because it makes the offending value 
obvious. In particular,
if for example you called this incorrectly and had the temperature in there 
instead of the scale
that will be trivial to debug from the message.

Of course, you actually want to be able to test any scal evalue for validity, 
not just the one
stuffed into your instance (.scale). So lets revisit the validScale method:

def validScale(self, scale):
return scaleName.upper() in ('F', 'C', 'K')

You'll notice that it doesn't depend in "self". Or, for that matter, the class. 
So this is a
"static" method: a function defined in the class for conceptual clarity, but 
not with any
dependence on the class itself or a particular class instance. So:

@staticmethod
def validScale(scale):
return scaleName.upper() in ('F', 'C', 'K')

In __init__, and elsewhere, you can still call this from the instance:

def __init__(self, .....scale...):
if not self.validScale(scale):
raise ValueError("invalid scale %r: expected one of F, C or K" % (scale,))
You can also call this from _outside_ the class, for example for other 
validation:

scale = input("Enter a temperate scale name (F, C or K): ")
if not TempConverter.validScale(scale):
print("Bad! Bad user!")
 newScaleValid = True 

Again, validScale returns a Boolean. So you could have just gone:

newScaleValid = self.validScale(newScale)
 if scaleValid and newScaleValid:
print('Scale converted')
else:
msg = "There was and error with the scales entered.n"
msg = msg + "You entered: " + self.scale
msg = msg + ' ' 'and' + self.newScale
print(msg)

if __name__ == "__main__":
myclass = TempConverter(32, 'f', 'c')
myclass.convertTemp() 

My personal inclination would be do define a Temperature class with a convert 
function to be used
like this:

temp = Temperature(32, 'f')
tempC = temp.convert('c')

This reduces the complexity of the class and IMO makes it easier to use 
elsewhere.

BTW, you get an instance back from tempConverter(...), not a class. So don't 
call it "myclass".

Cheers,
Cameron Simpson <c...@cskk.id.au (mailto:c...@cskk.id.au)>
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to