子类整型以允许“未知”值

2024-04-26 13:17:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我有点困在这里了。我基本上处于实验阶段,我想知道我是否可以将int子类化,这样它就可以像你以前的好int一样起作用,只是你可以指定一个“未知”值,在算术运算的情况下,这个值将作为1。在

所以我可以说:

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

实际上,它在某种程度上与float('inf')相似,只是我只需要整数加上一个“特殊”值。在

我想象中的工作是这样的:

^{pr2}$

但是这个例子在我尝试将其实例化为uint('unknown')时抛出ValueError: invalid literal for int() with base 10: 'unknown'。在

这有可能吗?我该怎么做呢?在


背景级别1

如果有人问,背景是我有一个iterable列表,我想用itertools.product创建一个新的。但在此之前,我想利用__len__,以防某些迭代器实现它,以便能够猜测(最小)最终元素的数量。所以,对于那些没有__len__的iterable,我假设是1。在

我之所以要用class uint(int)来做这件事,是因为我希望能够安全地公开单独的计数(以便有人可以在日志中输入类似“loading(1500=10*10*unknown*15)elements”之类的内容,并且仍然传递其中一些“unknown”的信息。在

2级背景

我实际上在幻想这样一种情况:a库提供这个类用于iterable对象的定义__len__,这样它们就可以根据“最小值”、“最大值”或“最佳猜测”返回一个数字,而不必为它在一些简单数学中的进一步使用而烦恼。在

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

假设一个对象有一个迭代器来读取一个巨大的文件:为什么这个对象不能说“好吧,这个文件是400mib,那么至少有4000个记录”?在

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


Tags: 文件对象lencount情况算术floatiterable
3条回答

您可以使用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]

不完全确定您为什么要这样做,但以下方法应该有效:

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__()

这里的想法是,不是将int值存储在名为self.value的属性中,而是使用您要使用的值执行超级类的实例化。在

我认为有些概念上的问题比你的实现问题更重要。在

将“未知值”视为1可以使它们不是真正未知的。为了类比浮点数,这里有一个定义良好的"Not a Number",它将参与数学运算,但在大多数情况下会产生NaN。例如:

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

因为用这个算数生成的结果不应该是好的。如果按照您的建议实现“未知整数”,未知值将产生无意义的结果。例如:

^{pr2}$

你得到了一个正确的整数,但这真的是你想要的语义吗?另一个类似的情况是被零除,这在数学上是未定义的。任何一个值,只要能凑成适当的位置,就会产生数学上的荒谬。由于(x/y) * y == x(当且仅当y != 0)时,您可能会期望:

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

但你不能不打破数学。在

相关问题 更多 >