【问题标题】:Different behavior of arithmetics on dtype float 'object' and 'float'dtype float 'object' 和 'float' 上的不同算术行为
【发布时间】:2018-04-05 01:31:03
【问题描述】:

大家好,我只是 python 的新手(即使是编程),所以我的问题可能听起来很基础,但我很难理解。

为什么对“浮点对象”的算术有选择性行为?

import numpy as np

a = np.random.normal(size=10)
a = np.abs(a)
b = np.array(a, dtype=object)

np.square(a) # this works
np.square(b) # this works

np.sqrt(a) # this works
np.sqrt(b) # AttributeError: 'float' object has no attribute 'sqrt'

图片链接是我在本地jupyter notebook中的运行结果:

jupyter notebook 运行结果

欣赏有用的见解!谢谢


edit 050418 09:53 --添加一个我认为是类似问题的链接 Numpy AttributeError: 'float' object has no attribute 'exp'

【问题讨论】:

  • 作者提前道歉,因为他不知道如何输出ipython控制台直接在屏幕上显示结果>
  • 对于对象 dtype 数组,numpy 将计算委托给元素(有点像列表理解)。结果是某些计算有效,而另一些则无效。你找到了一对可以说明这一点。两者都是编译的,因此很难看出委托有何不同。
  • 嗨@hpaulj ...您的意思是在文档中编译吗?上次我在里面搜索时没有找到任何东西。你能提供任何链接吗? tq
  • 我用ipython 双问号检查 Python 代码:?? 作为一般规则,不要指望对对象 dtype 数组进行数学运算。它是命中注定的。即使它有效,它也比数字 dtypes 慢。
  • numpy square 知道它可以将操作委托给对象的 __mul__ 方法(如果有的话),Python float 对象会这样做。如果一个对象有一个sqrt 方法,numpy.sqrt 将委托给它。 Python float 没有 sqrt 方法。

标签: python numpy


【解决方案1】:

@Warren 指出 square '代表'乘法。我通过创建一个包含列表的对象数组来验证这一点:

In [524]: arr = np.array([np.arange(3), 3, [3,4]])
In [525]: np.square(arr)
TypeError: can't multiply sequence by non-int of type 'list'

square 作用于数组的其余部分:

In [526]: np.square(arr[:2])
Out[526]: array([array([0, 1, 4]), 9], dtype=object)

sqrt 不适用于以下任何一种:

In [527]: np.sqrt(arr)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-527-b58949107b3d> in <module>()
----> 1 np.sqrt(arr)

AttributeError: 'numpy.ndarray' object has no attribute 'sqrt'

我可以让sqrt 使用自定义类:

class Foo(float):
    def sqrt(self):
        return self**0.5

In [539]: arr = np.array([Foo(3), Foo(2)], object)
In [540]: np.square(arr)
Out[540]: array([9.0, 4.0], dtype=object)
In [541]: np.sqrt(arr)
Out[541]: array([1.7320508075688772, 1.4142135623730951], dtype=object)

【讨论】:

    【解决方案2】:

    不确定是否是这个原因,但我的猜测是:

    如果您的对象是您自己的自制类的实例怎么办? Numpy 不能做任何其他事情,但希望你在你的类中定义了一个 sqrt 方法并让它完成工作。所以我假设这就是它在这里所做的,但在你的情况下,你的对象是浮动的,虽然np.sqrt(some_random_float) 是有道理的,some_random_float.sqrt() 不是因为AttributeError: 'float' object has no attribute 'sqrt'

    通常 numpy 是为数值计算而设计和优化的,虽然将它与通用 dtype=object 一起使用有时会很方便,但您不应该假设在这种情况下一切都将始终无缝运行...

    【讨论】:

    • 好吧,这就是逻辑。但是像 .square() 这样的实例呢?是不是表示 np 列出了一些常见的实例,本例中包含了 square()?
    【解决方案3】:

    在 Python 中,一切都是对象。

    操作符在对象上实现为特殊方法(从方法名称中的__前缀可以看出,例如a + ba.__add__(b)的语法糖,或者它们是内置函数的别名,将对象作为参数(例如a ** bpow(a, b) 的语法糖。通常,函数本身是对象上特殊方法的别名(例如iter(a) 只是返回a.__iter__())。

    Numpy 添加了进一步的语法糖,它实现了基于 numpy 对象类型的函数。如上所述,具有 object dtype 的 numpy 数组将运算符的实现推回到数组中元素的对象类型(所以基本上,np.square(a) 在语义上类似于array = map(lambda x: x*x, array),它实际上被评估为@987654330 @。

    请注意,sqrt 不作为内置函数存在(它是从标准库中的 math 模块或 np 的实现中导入的,或者使用 **0.5(实际上是 pow(x, 0.5)),因此普通的float 对象不会有实现它的方法。

    【讨论】:

    • 很好的解释谢谢! hpaulj 答案中显示的示例就是对此的证明
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2014-12-16
    • 2023-03-19
    • 2014-08-09
    相关资源
    最近更新 更多