Je voudrais implémenter un objet, qui limite les valeurs dans une plage donnée après que les opérations arithmétiques lui ont été appliquées. Le code ci-dessous fonctionne bien, mais je suis en train de réécrire inutilement les méthodes. Il y a sûrement une façon plus élégante de le faire. Une métaclasse est-elle le chemin à parcourir?Opérateurs arithmétiques de décoration | devrais-je utiliser une métaclasse?
def check_range(_operator):
def decorator1(instance,_val):
value = _operator(instance,_val)
if value > instance._upperbound:
value = instance._upperbound
if value < instance._lowerbound:
value = instance._lowerbound
instance.value = value
return Range(value, instance._lowerbound, instance._upperbound)
return decorator1
class Range(object):
'''
however you add, multiply or divide, it will always stay within boundaries
'''
def __init__(self, value, lowerbound, upperbound):
'''
@param lowerbound:
@param upperbound:
'''
self._lowerbound = lowerbound
self._upperbound = upperbound
self.value = value
def init(self):
'''
set a random value within bounds
'''
self.value = random.uniform(self._lowerbound, self._upperbound)
def __str__(self):
return self.__repr__()
def __repr__(self):
return "<Range: %s>" % (self.value)
@check_range
def __mul__(self, other):
return self.value * other
@check_range
def __div__(self, other):
return self.value/float(other)
def __truediv__(self, other):
return self.div(other)
@check_range
def __add__(self, other):
return self.value + other
@check_range
def __sub__(self, other):
return self.value - other
Je pense que cela répond le plus clairement à la question OPs, mais je pense que l'autre réponse apporte une solution légèrement meilleure au problème. – Omnifarious
Wow, merci beaucoup Matt. Je suis d'accord que la solution où vous n'utilisez ni décorateurs ni métaclasses est la plus propre. Merci beaucoup de me montrer le type (auto) idée et comment appliquer les décorateurs automagiquement. Très instructif, merci beaucoup! – Jelle
Une question sur le type intéressant (auto) modèle: classe RRRange (Plage): def __init __ (self, * args): Range.__init __ (self, * args) def whatsmytype (auto): type de retour (auto) RNG = RRRange (7, 0, 10) impression RNG + 5 # retourne une plage, ni objet RRRange Comment est le type (self) (val, rng._lowerbound, rng._upperbound) différent de Plage (auto) (val, rng._lowerbound, rng._upperbound)? En y réfléchissant, l'approche de la métaclasse aurait eu plus de sens s'il n'était pas nécessaire de redéfinir l'opérateur arithmétique. Je suis curieux de savoir si c'est faisable? – Jelle