Using min and max to limit values to a range in Python
Question:
I have this small python file that I wrote in Python 2.7.9 and now I am testing it in Python 3.4.3.
All works, for I am able to send commands to my RPI. But when I send the command to change the volume on the speaker (ranging 1-100), they are all read by the python script as 100%.
Example:
Volume 26
, is seen as Volume 100. I add commented out the line with volume = … and it works now but I can not prevent people from spamming the volume to the max @ 100%.
Code:
def setVolume(volume):
volume = max(60, min(30, volume)) #Volume Spam Protection
sendPost(speakerAddress+"volume","<volume>"+str(volume)+"</volume>")
Answers:
I am guessing when you say volume 26
is seen as 100%
, you mean it comes as 60
.
That is because of the line –
max(60, min(30, volume))
This roughly translates to , minimum between 30 and volume, and maximum between volume and 60 , so you would always get 60 , since if volume is greater than 30, you would get 30 from the inner min()
, and from outer max()
you would get 60. You can think what would happen for volume less than 30.
You actually want to do –
volume = min(60, max(30, volume))
I am not sure how this would have been working in Python 2.7 , according to the above condition the issue should have been there for Python 2.7 as well.
I guess, what you really want is that your volume is in the range 30..60. In this case you should swap you min/max line to this:
volume = min(60, max(30, volume))
So you get the maximum of the volume and 30 — (at least 30) — and the minimum of that result and 60 — maximum 60.
Much more readable would be to not use min
and max
at all; they are efficient for find the extrema of an arbitrary number of arguments, but overkill for only two.
if volume < 30:
volume = 30
elif volume > 60:
volume = 60
(This would have the side effect of fixing any logic errors resulting from the nested construction you were using.)
I have written a well readable function limit
for that purpose:
def limit(iMin, iVal, iMax):
return min(iMax, max(iMin, iVal))
volume = limit(30, volume, 60)
I have this small python file that I wrote in Python 2.7.9 and now I am testing it in Python 3.4.3.
All works, for I am able to send commands to my RPI. But when I send the command to change the volume on the speaker (ranging 1-100), they are all read by the python script as 100%.
Example:
Volume 26
, is seen as Volume 100. I add commented out the line with volume = … and it works now but I can not prevent people from spamming the volume to the max @ 100%.
Code:
def setVolume(volume):
volume = max(60, min(30, volume)) #Volume Spam Protection
sendPost(speakerAddress+"volume","<volume>"+str(volume)+"</volume>")
I am guessing when you say volume 26
is seen as 100%
, you mean it comes as 60
.
That is because of the line –
max(60, min(30, volume))
This roughly translates to , minimum between 30 and volume, and maximum between volume and 60 , so you would always get 60 , since if volume is greater than 30, you would get 30 from the inner min()
, and from outer max()
you would get 60. You can think what would happen for volume less than 30.
You actually want to do –
volume = min(60, max(30, volume))
I am not sure how this would have been working in Python 2.7 , according to the above condition the issue should have been there for Python 2.7 as well.
I guess, what you really want is that your volume is in the range 30..60. In this case you should swap you min/max line to this:
volume = min(60, max(30, volume))
So you get the maximum of the volume and 30 — (at least 30) — and the minimum of that result and 60 — maximum 60.
Much more readable would be to not use min
and max
at all; they are efficient for find the extrema of an arbitrary number of arguments, but overkill for only two.
if volume < 30:
volume = 30
elif volume > 60:
volume = 60
(This would have the side effect of fixing any logic errors resulting from the nested construction you were using.)
I have written a well readable function limit
for that purpose:
def limit(iMin, iVal, iMax):
return min(iMax, max(iMin, iVal))
volume = limit(30, volume, 60)