鸭子输入 numpy 浮点类型

Duck typing numpy float types

我正在编写与 msgpack-python 一起使用的自定义编码函数。我希望在让 msgpack-python 序列化之前将任何 numpy.float 对象转换为浮动对象。我的编码函数如下所示:

def encode_custom(obj):        
    if issubclass(obj.__class__,np.float):
        obj = float(obj)
    return obj

效果很好。但是,How do I check (at runtime) if one class is a subclass of another? 上投票最高的答案表明这是个坏主意。我认为这是因为此方法不使用鸭子类型。

有没有办法鸭式编码函数?

编辑:请注意,我只想将类似浮点数的对象转换为浮点数。更好地表示为另一种类型(例如整数)的对象应该使用其他类型,即使它们可以 float()'' 到 float 对象。

您可以调用将 NumPy 标量转换为 Python 标量的 NumPy 例程之一:

try:
    return obj.item()
except AttributeError:
    return obj

try:
    return obj.tolist() # yes, tolist. It won't return a list here.
except AttributeError:
    return obj

请注意,最好只使用 isinstance(obj, numpy.float64)isinstance(obj, (numpy.float32, numpy.float64))。鸭子类型对于像可迭代对象这样的东西很有意义,你尝试将它们视为可迭代对象,如果它有效,你就知道它们是可迭代对象。这里?您尝试将您的对象视为一个 numpy 标量,如果它有效,您就会知道...该对象具有 item 方法或 tolist 方法。那不是您真正感兴趣的信息。

如果您想检查对象是否具有实际的特定类型,而不是检查它提供的操作,isinstance 通常是可行的方法。

任何 python 问题的第 1 个答案是 "it depends"。使用鸭子类型,您只需假设其正确并在一切出错时捕获异常即可使用该对象。在你的情况下,那将是:

def encode_custom(obj):
    """Strict type checking: change to float, but raise ValueError
    on fail and let upper level deal with it."""
    return float(obj)

def encode_custom(obj):
    """Loose type checking: change to float or return unchanged"""
    try:
        return float(obj)
    except ValueError:
        return obj

这适用于各种浮点数以及可以转换为浮点数的所有内容。诸如 np.int16np.bool_str 之类的东西(如果它恰好代表一个 int 或 float)。现在到 "it depends"。如果您希望所有这些东西都隐蔽或糟糕,如果您的程序将这些非浮动的东西定义为垃圾并且您想出错,这很好。

在这种情况下,不要检查子类,而是检查实例,这样您就可以处理正在进行的任何奇怪的多重继承或元编程。

def encode_custom(obj):        
    if isinstance(obj,np.float):
        obj = float(obj)
    return obj

这里的类型的特殊外壳是完全合理的 - 因为听起来你正在将它输入一个无论如何都不适用于 duck-typing 的 API。

但是正如其他地方提到的,np.float is float,所以这是行不通的。您可能想要 isinstance(val, np.floating)isinstance(val, np.inexact).

为了将来参考,如果您想知道整个 class 层次结构(不包括 abcs)是什么,您可以使用 .__mro__ 属性 获取它:

>>> np.float32.__mro__
(<class 'numpy.float32'>, <class 'numpy.floating'>, <class 'numpy.inexact'>, <class 'numpy.number'>, <class 'numpy.generic'>, <class 'object'>)