Ни разу не пробовал Spyder редактор, установил, и как-то просто так написал это, может поможет:
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
class GeometryPrimitive:
def __init__(self, **kwargs):
self.parameters = {}
for key in kwargs:
self.parameters.update({key: {
'value': kwargs[key],
'validate': lambda x: True}
})
@property
def parnames(self):
if 'parameters' in self.__dict__:
return self.__dict__['parameters'].keys()
else:
return tuple()
def enter_parameters(self):
done = False
while not done:
for par in self.parameters:
status = False
while not status:
value = input('Enter value of {}:'.format(par))
status, err_msg = self.parameters[par]['validate'](value)
if not status:
print('Illegal value of the <{}> parameter: {}. Try again.'.format(par, err_msg))
else:
self.parameters[par]['value'] = value
done, err_msg = self.validate()
if not done:
print(err_msg)
def validate(self):
'''Parameter related validation '''
return False, ''
def area(self):
raise NotImplemented
def __getattr__(self, attr):
if attr in self.parnames:
# one can define broadcast coercion to numeric -, e.g. float type
return self.parameters[attr]['value']
else:
return super().__getattr__(attr)
def __setattr__(self, attr, value):
if attr in self.parnames:
self.parameters[attr] = value
else:
super().__setattr__(attr, value)
@staticmethod
def _is_positive_number(value):
try:
value = float(value)
except ValueError:
return (False, "the value isn't a numerical value")
if value >= 0.0:
return (True, "")
else:
return (False, "the value should be positive")
class Rectangle(GeometryPrimitive):
def validate(self):
return True, ''
def __init__(self, width=0, height=0):
super().__init__(width=width, height=height)
# initialize validation values
self.parameters['width']['validate'] = self._is_positive_number
self.parameters['height']['validate'] = self._is_positive_number
@property
def area(self):
return float(self.width) * float(self.height)
class Triangle(GeometryPrimitive):
def validate(self):
'''
Related validation. Check if the entered values can be treated as
edge length's of a triangle.
'''
_test = sorted(map(float, [self.AB, self.AC, self.BC]))
print('validation:', _test)
if _test[0] + _test[1] >= _test[-1]:
return True, ''
else:
return False, 'Impossible values. Try again.'
def __init__(self, AB=0, AC=0, BC=0):
super().__init__(AB=AB, AC=AC, BC=BC)
# initialize validators
self.parameters['AB']['validate'] = self._is_positive_number
self.parameters['BC']['validate'] = self._is_positive_number
self.parameters['AC']['validate'] = self._is_positive_number
@property
def area(self):
print("It is too tricky to compute area of the triangle..."
"Use Heron's formula to implement this."
"Do you wait something*** Sorry, I can compute perimeter only...")
return self.perimeter
@property
def perimeter(self):
return float(self.AB) + float(self.BC) + float(self.AC)
menu = {1: Rectangle(),
2: Triangle()
}
done = False
while not done:
ans = input("Make your choice (or `q` for quit): {}:".format(';'.join(map(lambda x: '%s -- %s' % (x, menu[x].__class__.__name__), menu))))
err_msg = ''
try:
if int(ans) in menu:
menu[int(ans)].enter_parameters()
print('The area of the object is ', menu[int(ans)].area)
except ValueError:
err_msg = "Illegal input."
if ans == 'q': done = True
if err_msg and not done: print(err_msg)