2013-09-23 25 views
3

我有点卡在这里。我基本上处于试验阶段,我不知道我是否可以继承int,以便它能够像您的好老int一样行动,除了您将能够分配一个“未知”值,在算术运算的情况下,它将采取行动为1子类int允许“未知”值

所以,我可以说:

>>> uint(5) + 5 
10 
>>> uint('unknown') 
unknown 
>>> int(uint('unknown')) 
1 
>>> uint('unknown') + 5 
6 
>>> 

事实上,它在某种程度上类似于已经与float('inf')工作,但我只需要加上一个“特殊”的值的整数。

什么我想象到工作将沿着线的东西:

class uint(int): 

    def __init__(self, value): 
     self.value = value 
     self.unknown = self.value == "unknown" 

    def __int__(self): 
     return 1 if self.unknown else self.value 

    def __str__(self): 
     return "unknown" if self.unknown else str(self.value) 

但这个例子引发ValueError: invalid literal for int() with base 10: 'unknown'当我尝试实例化它作为uint('unknown')

这是可能的吗?我会怎么做呢?


背景水平1

万一有人问,背景是,我有iterables的名单,我想创建一个使用itertools.product新的。但之前,我想利用__len__,以防某些迭代器实现它,以便能够猜出(最小)最终元素数量。所以在最后的数量而言,对于那些iterables不具备__len__,我假设1.

原因,我想class uint(int)要做到这一点,我希望能够揭露单独计数安全地(这样有人可以推送日志类似于:“加载(1500 = 10 * 10 *未知* 15)元素”并且仍然传递其中一些是“未知”的信息

背景级别2

我真的很喜欢当一个库提供这个类用于定义可迭代对象'__len__,以便他们可以基于“最小”,“最大”或“最佳猜测”返回一个数字,但仍未受到某些简单数学中进一步使用的困扰。

>>> count = uint(100, 'minimum') 
>>> print count 
"minimum of 100" 
>>> count * 20 
2000 
>>> 

想象一下,上面写着一个巨大的文件的迭代器的对象:为什么不能对象说“好了,该文件是400 MIB,所以会有至少4000条记录”?

所以一个奖金问题:什么更简单:子类化int或创建一个新的类,但必须实现和维护aritmethic操作接口?

+5

为什么'1'?这背后的语义是什么?另外,这与“int”字段也可以是“None”不同? –

+1

如果您正在寻找处理未知的一组观测值的方法,那么有许多标准方法可以处理。但那会是一个与你所问的不同的问题。 – msw

+0

我已经阅读了三次您添加的“背景”,它似乎没有让您的目标更明确。然而,“我应该子类int”更明显是“不”。无论你的“未知”是什么,它都会失败OO Design的“** is-a ** int”测试。 – msw

回答

2

不完全知道你为什么会想这样做,但下面应该工作:

class uint(int): 
    def __new__(cls, value): 
     unknown = value == 'unknown' 
     obj = super(uint, cls).__new__(cls, 1 if unknown else value) 
     obj.unknown = unknown 
     return obj 

    def __str__(self): 
     return 'unknown' if self.unknown else super(uint, self).__str__() 

这里的想法是,与其在一个名为self.value属性存储你的int值,执行的实例具有您想要使用的值的超类。

+0

嗯,这工作。除了读完msw的评论和回答之后,我可能会重新思考我的策略,但是你的解决方案是有效的,并告诉我如何打破数学。接受。 –

3

我认为有一些概念性问题超出了你的实现问题。

将“未知值”视为1使其不是真正的未知数。为了对浮点数进行类比,有一个明确定义的"Not a Number",它将参与数学运算,但在大多数情况下产生NaN。例如:

>>> f = float('NaN') 
>>> 42 * f 
nan 

这是一件好事,因为NaN的真的不是那么算术使用不应该产生看似有效的结果的一个数字。如果您按照您的建议实施了“未知整数”,则未知值将产生无意义的结果。例如:

>>> u = uint('unknown') 
>>> 42 * u 
42 

你找回了一个合适的整数,但这真的是你想要的语义吗?另一个类似的情况是被零除,这在数学上是未定义的。任何可能被挖掘的价值都会产生数学上的荒谬。由于(x/y) * y == x(当且仅当y != 0),你可能会认为:

>>> (42/0) * 0 # this doesn't really work 
42 

但你不能这样做,不破坏数学。

+0

因为你的回答,我马上进入了Python解释器并输入'x =(42/0)* 0',预计会得到42作为某种隐藏的复活节彩蛋。我非常失望。 :(+1反正 – Shashank

+0

你认为它会给生命,宇宙和一切带来答案吗?对不起,令人失望;)我已经明确无效了,这要感谢暗示的更正。 – msw

2

您可以使用None作为尚未分配值的占位符。例如:

>>> a = [4, 3, 1, 5, 2, None, None] 
>>> len(a) 
7 
>> a*3 
[4, 3, 1, 5, 2, None, None, 4, 3, 1, 5, 2, None, None, 4, 3, 1, 5, 2, None, None] 
相关问题