我对编程比较陌生。作为一名物理老师,我正在努力学习Python,因为我不想给孩子们上编码入门课。目前我正在学习数组。作为我自己的一个实践,我尝试用np.fromfunction()创建levi-Cita-tensor。它似乎不接受一个以上的逻辑条件,这个问题可能与数组和列表的不同性质有关,但我不明白到底出了什么问题。
我写了一个函数来检查两个或三个索引是否相同(返回0),如果不是,则索引是循环的(返回1)还是反循环的(返回-1)。当使用np.fromfunction()中的函数时,我得到:
ValueError:具有多个元素的数组的真值是不明确的。使用.any()或a.all()
而不是无聊的人在这个网站上与我可能不那么优雅的书面功能;)我尝试了一个更简单的命令来测试np.fromfunction()中逻辑条件的使用:
np.fromfunction(lambda i, j, k: i == j, (3,3,3), dtype=int)
它返回一个带有布尔数据的数组
但如果我使用两个逻辑条件,例如:
np.fromfunction(lambda i, j, k: i==j or j==k, (3,3,3), dtype=int)
我得到的valueError和我原来的函数一样。我可能没有正确理解矢量化的概念。在我对这个过程的理解中,计算机从位置i=0,j=0,k=0开始,执行两个逻辑条件,en返回位置i=0,j=0,k=0的真值。它似乎只对一个逻辑条件起作用,为什么不对两个(或更多)逻辑条件起作用呢?
2条答案
按热度按时间mw3dktmi1#
您好,欢迎来到网站!谢谢你的深思熟虑的问题!
不幸的是,这些文档(在我看来)对
np.fromfunction
来说并不是很好。我认为我们都期望的是,它是这样实现的:这意味着
your_func
的执行次数与索引的三元组一样多。然而,查看源代码,它的实现更像是:
这意味着
your_func
只被调用一次,不是用标量,而是用每个i
,j
和k
填充的Tensor。那看起来像什么?使用print
尝试np.fromfunction
:这就是
np.indices
返回的数组。因此,
np.fromfunction
的输入函数需要能够处理整个数组作为输入,而or
-ing两个数组不起作用!我建议远离
np.fromfunction
,即使你设法向量化你的代码。相反,您可以使用broadcasting
(提示:直接使用sparse=True
),使您的代码更好。相反,你也可以遍历所有的索引,并像在初始伪代码中那样多次调用你的函数!
为什么我们不能
or
两个numpy数组?这是由于Python的限制。当你写
a or b
时,python会检查a
是否是“Truthy”(即通过调用bool(a)
),然后如果检查是True
,则返回a
,否则返回b
。这种行为被称为短路,并可能导致some useful tricks。因此,当
a
和b
是numpy数组时,python在a
上调用bool
,numpy响应数组的真值(或“truthyness”)是不明确的。这是有意义的,因为应该如何处理一个同时填充了True
和False
的数组?;)值得庆幸的是,numpy实现了一个函数(
np.logical_or
)来复制所需的行为。对于布尔数组,“按位或”运算符|
也是这样工作的。但是由于运算符优先级的原因,你必须注意在表达式中加上括号,就像hpaulj在他的评论中所做的那样。希望这对你有帮助!
omhiaaxx2#
为'[numpy] fromfunction'搜索SO表明这个函数已经被误解了很长一段时间。我怀疑这更多的是一个一厢情愿的问题,而不是文档本身。源代码是令人难以置信的简单,远远短于文档,旧的或重写,暗示。
它所做的就是生成一些索引数组,并将它们传递给你的函数。没有神奇的“矢量化”或逐个单元的迭代。这个动作,如果有的话,必须内置到你自己的函数中。
indices
创建一个数组:可以使用
meshgrid
或mgrid
。让我们把这个数组解压缩成两个(基本的python功能):
所以我们现在有两个(或者在你的例子3中)数组。我们可以用这些来做各种计算。请参阅numpy基础文档以获得一些想法。
例如,我们可以做
I+J
。但根据你的情况,我们可以比较一下:结果是相同形状的布尔数组。这种逐元素比较的能力内置于numpy数组的编译方法中。在这里,它们在形状上是匹配的,但是
broadcasting
增加了一些魔力,允许我们在一定范围内处理不同形状的数组。但是如果我尝试使用2个测试,我会得到'ambiguity'错误:
这是一个独立于
fromfunction
的问题,尽管相当常见。当我们试图在python上下文中使用需要标量布尔值的数组时,就会得到这样一个错误。if
子句是一个经典的例子,但这里是or
-它有一个试图短路的底层if
。我们需要做的是使用()来控制精度,
|
来执行元素逻辑运算。在好的numpy代码中,我们尝试使用编译后的方法来处理整个数组。这可能需要思维的转变。所以当我们想做一些只能用标量表示的事情时
用这些术语来思考:在[100]中:def foo(i,j):...:if(j>0)or(i==j):.:return True.:else:.:return False.:
使用nest list comprehension:
尝试将我们的
indices
数组应用于此函数会产生模糊性错误:有一个函数可以将数组应用于这样的标量函数,尽管我有点犹豫要不要演示它,因为它也经常被误用,
它的文档,包括一个性能免责声明,是一个有点清楚。
对不起,这比我预期的要长得多,但希望这里有一些有用的东西。