Reputation: 406
I have an object that contains the values for two differential equations.
for example:
#create equation object
class EquationValues(object):
x = 0
y = 0
xMin = 0
xMax = 0
yMin = 0
yMax = 0
deltaTime = 0
# Class constructor/initilizer
def __init__(self, x, y, xMin, xMax, yMin, yMax, deltaTime):
self.x = x
self.y = y
self.xMin = xMin
self.xMax = xMax
self.yMin = yMin
self.yMax = yMax
self.deltaTime = deltaTime
def make_equationValues(x, y, xMin, xMax, yMin, yMax, deltaTime):
equationValues = EquationValues(x, y, xMin, xMax, yMin, yMax, deltaTime)
return equationValues
with open ('inputs.csv', 'r') as f:
reader = csv.reader(f, delimiter = ',')
data = list(reader)
rowCount = len(data)
while x < rowCount:
try:
# Set variables and make sure they are the right format
x = float(data[x][0])
y = float(data[x][1])
xMin = float(data[x][2])
xMax = float(data[x][3])
yMin = float(data[x][4])
yMax = float(data[x][5])
deltaTime = float(data[x][6])
# Check for negative input, if negative throw value error
if (x < 0) or (y < 0) or (xMin < 0) or (xMax < 0) or (yMin < 0) or ( yMax < 0) or (deltaTime < 0):
raise ValueError
how can I check all of the values for negative numbers efficiently?
Currently, I am able to do it by using and if statement in a try/except
for example:
if (x < 0) or (y < 0) or (xMin < 0) or (etc):
raise ValueError
This doesn't seem like the best way to do it. Is there a better way to do this?
Upvotes: 0
Views: 1057
Reputation: 913
The example here is copied from Python Descriptors Demystified.
You should use descriptors to store attributes that must be constrained to certain values. The descriptor can be used to prevent invalid values from being set on any attribute defined using the descriptor class:
from weakref import WeakKeyDictionary
class NonNegativeNumber(object):
def __init__(self):
self.data = WeakKeyDictionary()
def __get__(self, obj, objtype):
return self.data.get(obj, 0)
def __set__(self, obj, val):
if val < 0:
raise ValueError('must be nonnegative value')
self.data[obj] = val
Then your original class would look like:
class EquationValues(object):
x = NonNegativeNumber()
y = NonNegativeNumber()
xMin = NonNegativeNumber()
xMax = NonNegativeNumber()
yMin = NonNegativeNumber()
yMax = NonNegativeNumber()
deltaTime = NonNegativeNumber()
def __init__(self, x, y, xMin, xMax, yMin, yMax, deltaTime):
self.x = x
self.y = y
self.xMin = xMin
self.xMax = xMax
self.yMin = yMin
self.yMax = yMax
self.deltaTime = deltaTime
Upvotes: 1
Reputation: 33714
You can use the any
statement to check if any of them is negative.
class EquationValues(object):
def __init__(self, x, y, xMin, xMax, yMin, yMax, deltaTime):
self.x = x
self.y = y
self.xMin = xMin
self.xMax = xMax
self.yMin = yMin
self.yMax = yMax
self.deltaTime = deltaTime
negatives = any(v for v in {x,y,xMin,xMax,yMin,yMax,deltaTime} if v < 0)
if negatives:
raise ValueError("One variable is negative")
EquationValues(0,0,0,0,0,0,-1)
# ValueError: "One variable is negative"
You can also use locals()
to get a dict of the current local scope variables.
class EquationValues(object):
def __init__(self, x, y, xMin, xMax, yMin, yMax, deltaTime):
self.x = x
self.y = y
self.xMin = xMin
self.xMax = xMax
self.yMin = yMin
self.yMax = yMax
self.deltaTime = deltaTime
if [v for v in locals().values() if isinstance(v, int) if v < 0]:
raise ValueError("One variable is negative")
EquationValues(0,0,0,0,0,0,-1)
# ValueError: "One variable is negative"
Upvotes: 1
Reputation: 50190
If your code actually works (it wouldn't work if these are attributes), you can rewrite it like this:
if any(var < 0 for var in (x, y, xMin, xMax, yMin, yMax, deltaTime)):
raise ValueError
Since the variables you want to check are just a collection of names, there isn't much more you can do. If they were a list, dictionary or NamedTuple
etc., there would be more room for improvement.
If the check is supposed to take place in make_equationValues()
(but why didn't you just put the check in the constructor?) and you have a lot more variables than you show, you could streamline the check like this:
def make_equationValues(*args):
if any(var < 0 for var in args):
raise ValueError
return EquationValues(*args)
But I wouldn't recommend this, because you no longer have an argument signature for your function, which makes it error-prone and hard to maintain.
Upvotes: 1