通常,NaN(不是数字)通过计算传播,所以我不需要在每个步骤中检查 NaN。这几乎总是有效,但显然也有异常(exception)。例如:

>>> nan = float('nan')
>>> pow(nan, 0)
1.0

我在此找到了 following comment:



有没有办法通过Python检查上面提到的INVALID标志?或者,是否有其他方法可以捕获 NaN 不传播的情况?

动机:我决定对缺失数据使用 NaN。在我的应用程序中,缺少输入应该导致缺少结果。它工作得很好,除了我描述的。

最佳答案

我意识到自从被问到这个问题已经过去一个月了,但我遇到了一个类似的问题(即 pow(float('nan'), 1) 在某些 Python 实现中抛出异常,例如 Jython 2.52b2),我发现上面的答案并不是我想要的正在寻找。

使用 6502 建议的 MissingData 类型似乎是要走的路,但我需要一个具体的例子。我尝试了 Ethan Furman 的 NullType 类,但发现这不适用于任何算术运算,因为它不强制数据类型(见下文),而且我也不喜欢它明确命名每个被覆盖的算术函数。

从 Ethan 的示例和调整代码开始,我找到了 here ,我到达了下面的类(class)。尽管该类被大量注释,但您可以看到它实际上只有少数几行功能代码。

关键点是:
1. 使用 coerce() 为混合类型(例如 NoData + float)算术运算返回两个 NoData 对象,以及基于字符串(例如 concat)运算的两个字符串。
2. 使用 getattr() 为所有其他属性/方法访问返回一个可调用的 NoData() 对象
3. 使用 call() 实现 NoData() 对象的所有其他方法:通过返回 NoData() 对象

下面是它的一些使用示例。

>>> nd = NoData()
>>> nd + 5
NoData()
>>> pow(nd, 1)
NoData()
>>> math.pow(NoData(), 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: nb_float should return float object
>>> nd > 5
NoData()
>>> if nd > 5:
...     print "Yes"
... else:
...     print "No"
...
No
>>> "The answer is " + nd
'The answer is NoData()'
>>> "The answer is %f" % (nd)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: float argument required, not instance
>>> "The answer is %s" % (nd)
'The answer is '
>>> nd.f = 5
>>> nd.f
NoData()
>>> nd.f()
NoData()

我注意到将 pow 与 NoData() 一起使用会调用 ** 运算符,因此可以与 NoData 一起使用,但使用 math.pow 不会因为它首先尝试将 NoData() 对象转换为浮点数。我很高兴使用非数学 pow - 希望 6502 等在上面的评论中遇到 pow 问题时使用 math.pow。

我想不出解决方法的另一个问题是使用格式 (%f) 运算符......在这种情况下没有调用 NoData 的方法,如果您不提供浮点数,运算符就会失败。无论如何,这就是类(class)本身。
class NoData():
"""NoData object - any interaction returns NoData()"""
def __str__(self):
    #I want '' returned as it represents no data in my output (e.g. csv) files
    return ''

def __unicode__(self):
    return ''

def __repr__(self):
    return 'NoData()'

def __coerce__(self, other_object):
    if isinstance(other_object, str) or isinstance(other_object, unicode):
        #Return string objects when coerced with another string object.
        #This ensures that e.g. concatenation operations produce strings.
        return repr(self), other_object
    else:
        #Otherwise return two NoData objects - these will then be passed to the appropriate
        #operator method for NoData, which should then return a NoData object
        return self, self

def __nonzero__(self):
    #__nonzero__ is the operation that is called whenever, e.g. "if NoData:" occurs
    #i.e. as all operations involving NoData return NoData, whenever a
    #NoData object propagates to a test in branch statement.
    return False

def __hash__(self):
    #prevent NoData() from being used as a key for a dict or used in a set
    raise TypeError("Unhashable type: " + self.repr())

def __setattr__(self, name, value):
    #This is overridden to prevent any attributes from being created on NoData when e.g. "NoData().f = x" is called
    return None

def __call__(self, *args, **kwargs):
    #if a NoData object is called (i.e. used as a method), return a NoData object
    return self

def __getattr__(self,name):
    #For all other attribute accesses or method accesses, return a NoData object.
    #Remember that the NoData object can be called (__call__), so if a method is called,
    #a NoData object is first returned and then called.  This works for operators,
    #so e.g. NoData() + 5 will:
    # - call NoData().__coerce__, which returns a (NoData, NoData) tuple
    # - call __getattr__, which returns a NoData object
    # - call the returned NoData object with args (self, NoData)
    # - this call (i.e. __call__) returns a NoData object

    #For attribute accesses NoData will be returned, and that's it.

    #print name #(uncomment this line for debugging purposes i.e. to see that attribute was accessed/method was called)
    return self

关于python - 通过计算传播 NaN,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10034455/

10-12 21:33