【问题标题】:Duck typing numpy float types鸭子打字 numpy 浮点类型
【发布时间】:2016-12-02 17:46:57
【问题描述】:

我正在编写一个用于 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? 的最高投票答案表明这是一个坏主意。我认为这是因为这种方法不使用鸭式打字。

有没有办法duck-type编码函数?

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

【问题讨论】:

  • try: return float(obj) except ValueError: return obj
  • @SethMMorton 这也将整数转换为浮点数。
  • 在某些情况下这是个坏主意。您已经明确表示要转换 numpy 浮点数,所以这看起来不错。但是我建议只使用isinstance(obj, np.float)
  • 仅供参考:numpy.float 只是 Python 内置 float 的另一个名称。如果每个人都使用float 而不是np.float,那就更清楚了。

标签: python numpy floating-point subclass duck-typing


【解决方案1】:

这里的类型的特殊大小写是完全合理的 - 因为听起来你正在将它输入一个无论如何都不能用于鸭子类型的 API。

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

为了将来参考,如果你想知道整个类层次结构(不包括abcs)是什么,你可以通过.__mro__属性得到它:

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

【讨论】:

  • 非常感谢mro 提示。
  • np.float32.mro(),即通过方法,其中MRO表示方法解析顺序
【解决方案2】:

您可以调用将 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))。 Duck 类型对于诸如可迭代对象之类的东西是有意义的,您尝试将它们视为可迭代对象,如果它有效,您就知道它们是可迭代对象。这里?您尝试将您的对象视为一个 numpy 标量,如果它有效,您就知道......该对象具有 item 方法或 tolist 方法。这不是您真正感兴趣的信息。

如果您想检查一个对象是否具有实际的、特定的类型,而不是检查它提供了什么操作,isinstance 通常是要走的路。

【讨论】:

    【解决方案3】:

    任何 Python 问题的第 1 个答案都是“取决于”。使用鸭子类型,您只需使用假设其正确的对象并在一切出错时捕获异常。在你的情况下,那将是:

    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)。现在到“这取决于”。如果您的程序将这些非浮动的东西定义为垃圾并且您想出错,那么如果您希望所有这些东西都隐藏起来或很糟糕,这是很好的。

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

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

    【讨论】:

    • 请注意,np.float 只是 Python 内置 float 的另一个名称。更重要的是,请注意 isinstance(np.float32(1.0), float) 返回 False
    • @WarrenWeckesser - 有趣。我检查了np.float64,它起作用了。 issubclass for np.float32 也不起作用。嗯....
    猜你喜欢
    • 2011-11-25
    • 2016-07-24
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 2012-10-26
    • 2011-03-23
    • 2011-05-11
    • 2020-02-13
    相关资源
    最近更新 更多