python-装饰算术运算符|我应该使用元类吗?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python-装饰算术运算符|我应该使用元类吗?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3820字,纯文字阅读大概需要6分钟。
内容图文
我想实现一个对象,该对象在对其进行算术运算后将值限制在给定范围内.下面的代码工作正常,但我毫无意义地重写了这些方法.当然,有一种更优雅的方法可以做到这一点.元类是路要走吗?
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
解决方法:
可以使用元类将装饰器应用于一组函数名,但是我认为这不是您要解决的方法.正如您所做的那样,使用@decorator语法在每个函数的基础上将装饰器应用到类主体中,我认为这是一个很好的选择. (我认为您的装饰器中有一个错误,顺便说一句:您可能不想将instance.value设置为任何值;算术运算符通常不会突变其操作数).
在您遇到的情况中,我可能会使用的另一种方法是完全避免使用装饰器,例如:
import operator
class Range(object):
def __init__(self, value, lowerbound, upperbound):
self._lowerbound = lowerbound
self._upperbound = upperbound
self.value = value
def __repr__(self):
return "<Range: %s>" % (self.value)
def _from_value(self, val):
val = max(min(val, self._upperbound), self._lowerbound)
# NOTE: it's nice to use type(self) instead of writing the class
# name explicitly; it then continues to work if you change the
# class name, or use a subclass
return type(self)(val, rng._lowerbound, rng._upperbound)
def _make_binary_method(fn):
# this is NOT a method, just a helper function that is used
# while the class body is being evaluated
def bin_op(self, other):
return self._from_value(fn(self.value, other))
return bin_op
__mul__ = _make_binary_method(operator.mul)
__div__ = _make_binary_method(operator.truediv)
__truediv__ = __div__
__add__ = _make_binary_method(operator.add)
__sub__ = _make_binary_method(operator.sub)
rng = Range(7, 0, 10)
print rng + 5
print rng * 50
print rng - 10
print rng / 100
印刷
<Range: 10>
<Range: 10>
<Range: 0>
<Range: 0.07>
我建议您在这种情况下不要使用元类,但是这是您可以使用的一种方法.元类是一个有用的工具,如果您感兴趣的话,很高兴了解如何在真正需要它们时使用它们.
def check_range(fn):
def wrapper(self, other):
value = fn(self, other)
value = max(min(value, self._upperbound), self._lowerbound)
return type(self)(value, self._lowerbound, self._upperbound)
return wrapper
class ApplyDecoratorsType(type):
def __init__(cls, name, bases, attrs):
for decorator, names in attrs.get('_auto_decorate', ()):
for name in names:
fn = attrs.get(name, None)
if fn is not None:
setattr(cls, name, decorator(fn))
class Range(object):
__metaclass__ = ApplyDecoratorsType
_auto_decorate = (
(check_range,
'__mul__ __div__ __truediv__ __add__ __sub__'.split()),
)
def __init__(self, value, lowerbound, upperbound):
self._lowerbound = lowerbound
self._upperbound = upperbound
self.value = value
def __repr__(self):
return "<Range: %s>" % (self.value)
def __mul__(self, other):
return self.value * other
def __div__(self, other):
return self.value / float(other)
def __truediv__(self, other):
return self / other
def __add__(self, other):
return self.value + other
def __sub__(self, other):
return self.value - other
内容总结
以上是互联网集市为您收集整理的python-装饰算术运算符|我应该使用元类吗?全部内容,希望文章能够帮你解决python-装饰算术运算符|我应该使用元类吗?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。