How call method from a method in same class?
Dave
dboland9 at offilive.com
Mon Apr 1 22:37:42 EDT 2019
On 4/1/19 10:29 PM, Cameron Simpson wrote:
> On 01Apr2019 22:02, Dave <dboland9 at 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 <cs at cskk.id.au>
Cameron,
I'm going to need a while to work through this. As I mentioned, this
was quick and dirty code just to illustrate a point - not intended to be
good code. So I'll take a close read tomorrow. Thanks again!!
Dave,
More information about the Python-list
mailing list