我想创建一个自定义数据类型,它基本上表现得像普通的int
,但值限制在给定范围内。我想我需要某种工厂功能,但我无法弄清楚如何去做。
myType = MyCustomInt(minimum=7, maximum=49, default=10)
i = myType(16) # OK
i = myType(52) # raises ValueError
i = myType() # i == 10
positiveInt = MyCustomInt(minimum=1) # no maximum restriction
negativeInt = MyCustomInt(maximum=-1) # no minimum restriction
nonsensicalInt = MyCustomInt() # well, the same as an ordinary int
任何提示都表示赞赏。谢谢!
答案 0 :(得分:5)
使用__new__
覆盖不可变类型的构造:
def makeLimitedInt(minimum, maximum, default):
class LimitedInt(int):
def __new__(cls, x= default, *args, **kwargs):
instance= int.__new__(cls, x, *args, **kwargs)
if not minimum<=instance<=maximum:
raise ValueError('Value outside LimitedInt range')
return instance
return LimitedInt
答案 1 :(得分:1)
Python中的赋值是一个语句,而不是表达式,因此无法在类型上定义赋值,因为赋值完全重新绑定了该名称。您可以做的最好的事情是定义一个set()
方法,该方法获取您想要的值,此时您可以创建一个“普通”类来处理验证。
答案 2 :(得分:1)
无需定义新类型:
def restrict_range(minimum=None, maximum=None, default=None, type_=int):
def restricted(*args, **kwargs):
if default is not None and not (args or kwargs): # no arguments supplied
return default
value = type_(*args, **kwargs)
if (minimum is not None and value < minimum or
maximum is not None and value > maximum):
raise ValueError
return value
return restricted
restricted_int = restrict_range(7, 49, 10)
assert restricted_int("1110", 2) == 14
assert restricted_int(16) == 16
assert restricted_int() == 10
try:
restricted_int(52)
assert 0
except ValueError:
pass
答案 3 :(得分:0)
您可以从python中的int
派生一个类,例如class MyInt(int)
,但python中的那个类型一旦创建就是不可变的(你不能改变它)。
你可以这样做:
class MyInt:
def __init__(self, i, max=None, min=None):
self.max = max
self.min = min
self.set(i)
def set(self, i):
if i > self.max: raise ValueError
if i < self.min: raise ValueError
self.i = i
def toInt(self):
return self.i
def __getattr__(self, name):
# Forward e.g. addition etc operations to the integer
# Beware that e.g. going MyInt(1)+MyInt(1)
# will return an ordinary int of "2" though
# so you'd need to do something like
# "result = MyInt(MyInt(1)+MyInt(1))
method = getattr(self.i, name)
def call(*args):
L = []
for arg in args:
if isinstance(arg, MyInt):
L.append(arg.toInt())
else: L.append(arg)
return method(*L)
return call
最好使用普通的验证功能,具体取决于你想要的功能,如果它更简单的话。
编辑:现在正在工作 - 恢复到更简单的早期版本,添加其他类似函数返回其他MyInt实例是不值得的: - )