问题
I am looking for an elegant way to ensure that a given variable remains positive.
I have two variables that hold positive float numbers and I decrement them according to certain conditions. At the end I want to guarantee that I still have positive numbers (or 0 at most). The pseudo code looks something like this:
list = [...]
value1 = N
value2 = M
for element in list:
if ... :
value1 -= X
if ... :
value2 -= Y
Is there a more elegant solution than just adding two ifs
at the end?
回答1:
I am unclear as to what you want to do -- either the variables can be negative, or they can't.
If you are decrementing a variable repeatedly and after doing so you want to check whether they are negative, do so with an
if
-- that's what it's for!if value < 0: # do stuff
If you think the variables should never be negative and you want to assert this fact in the code in the code, you do
assert value > 0
which may raise an
AssertionError
if the condition doesn't hold (assert
will not execute when Python is not run in debug mode).If you want the variable to be 0 if it has been decreased below 0, do
value = max(value, 0)
If you want the variable to be negated if it is negative, do
value = value if value > 0 else -value
or
value = abs(value)
回答2:
Use value1 = max(0, value1)
and the same for value2
at the end of the iteration.
回答3:
For floats, I like the max(0, value)
already given by Constantinius. You can even combine it with the decrement and use tuple unpacking to handle both values at once:
value1, value2 = max(0, value1-1), max(0, value2-1)
Some tricks for integers only (for the record, since I already posted them without realizing you were dealing with floats):
When decrementing you can use this:
value -= value and 1
Assuming the value always starts out >= 0, this won't let it get below 0.
When the value is zero, this evaluates to value -= 0
. When value is not zero, it evaluates to value -= 1
.
You could also use the ternary operator, which is more readable:
value -= 1 if value > 0 else 0
回答4:
Here's another take on it: a class which acts as a soft limit to the numbers value:
The numbers will never be in an invalid state:
SoftPositiveNumber(5) - 20 == 0
evaluates to true
from functools import total_ordering
@total_ordering
class SoftPositiveNumber(object):
"""This class acts like a number but will not allow
the contained value to be less than zero"""
def __init__(self, value):
if isinstance(value, SoftPositiveNumber):
value = value.value
self.value = value
if self.value < 0:
self.value = 0
def __str__(self):
return str(self.value)
def __int__(self):
return int(self.value)
def __float__(self):
return float(self.value)
def __repr__(self):
return f"SoftPositiveNumber({self.value})"
def __eq__(self, other):
if isinstance(other, SoftPositiveNumber):
return self.value == other.value
return self.value == other
def __lt__(self, other):
if isinstance(other, SoftPositiveNumber):
return self.value < other.value
return self.value < other
def __iadd__(self, other):
if isinstance(other, SoftPositiveNumber):
self.value += other.value
else:
self.value += other
if self.value < 0:
self.value = 0
return self
def __isub__(self, other):
if isinstance(other, SoftPositiveNumber):
self.value -= other.value
else:
self.value -= other
if self.value < 0:
self.value = 0
return self
def __add__(self, other):
if isinstance(other, SoftPositiveNumber):
return SoftPositiveNumber(self.value + other.value)
return SoftPositiveNumber(self.value + other)
def __sub__(self, other):
if isinstance(other, SoftPositiveNumber):
return SoftPositiveNumber(self.value - other.value)
return SoftPositiveNumber(self.value - other)
__rsub__ = __sub__
__radd__ = __add__
来源:https://stackoverflow.com/questions/7122535/python-ensuring-a-variable-holds-a-positive-number