我有一个接受参数 NBins
的函数。我想使用标量 50
或数组 [0, 10, 20, 30]
调用此函数。如何在函数中识别 NBins
的长度是多少?或者换一种说法,如果它是标量还是向量?
我试过这个:
>>> N=[2,3,5]
>>> P = 5
>>> len(N)
3
>>> len(P)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
>>>
如您所见,我无法将 len
应用于 P
,因为它不是数组.... python 中有类似 isarray
或 isscalar
的东西吗?
谢谢
type
?
>>> import collections.abc
>>> isinstance([0, 10, 20, 30], collections.abc.Sequence)
True
>>> isinstance(50, collections.abc.Sequence)
False
注意:isinstance
还支持类元组,应避免检查 type(x) in (..., ...)
且没有必要。
您可能还想检查 not isinstance(x, (str, unicode))
正如 @2080 和 here 所指出的,这不适用于 numpy
数组。例如。
>>> import collections.abc
>>> import numpy as np
>>> isinstance((1, 2, 3), collections.abc.Sequence)
True
>>> isinstance(np.array([1, 2, 3]), collections.abc.Sequence)
False
在这种情况下,您可以尝试 @jpaddison3 的答案:
>>> hasattr(np.array([1, 2, 3]), "__len__")
True
>>> hasattr([1, 2, 3], "__len__")
True
>>> hasattr((1, 2, 3), "__len__")
True
但是,如 here 所述,这也不是完美的,并且会错误地(至少在我看来)将字典分类为序列,而带有 collections.abc.Sequence
的 isinstance
会正确分类:
>>> hasattr({"a": 1}, "__len__")
True
>>> from numpy.distutils.misc_util import is_sequence
>>> is_sequence({"a": 1})
True
>>> isinstance({"a": 1}, collections.abc.Sequence)
False
您可以将您的解决方案自定义为类似的内容,根据您的需要向 isinstance
添加更多类型:
>>> isinstance(np.array([1, 2, 3]), (collections.abc.Sequence, np.ndarray))
True
>>> isinstance([1, 2, 3], (collections.abc.Sequence, np.ndarray))
True
以前的答案假设该数组是一个 python 标准列表。作为经常使用 numpy 的人,我建议对以下内容进行非常 Python 的测试:
if hasattr(N, "__len__")
__len__
属性(所以我猜,技术上不是标量类型)
if hasattr(N, '__len__') and (not isinstance(N, str))
将正确考虑字符串。
将@jamylak 和@jpaddison3 的答案结合在一起,如果您需要对 numpy 数组作为输入具有鲁棒性并以与列表相同的方式处理它们,您应该使用
import numpy as np
isinstance(P, (list, tuple, np.ndarray))
这对于列表、元组和 numpy 数组的子类是健壮的。
如果您还想对所有其他序列子类(不仅仅是列表和元组)保持健壮,请使用
import collections
import numpy as np
isinstance(P, (collections.Sequence, np.ndarray))
为什么要对 isinstance
进行这种处理,而不是将 type(P)
与目标值进行比较?这是一个示例,我们在其中创建和研究 NewList
的行为,NewList
是列表的一个普通子类。
>>> class NewList(list):
... isThisAList = '???'
...
>>> x = NewList([0,1])
>>> y = list([0,1])
>>> print x
[0, 1]
>>> print y
[0, 1]
>>> x==y
True
>>> type(x)
<class '__main__.NewList'>
>>> type(x) is list
False
>>> type(y) is list
True
>>> type(x).__name__
'NewList'
>>> isinstance(x, list)
True
尽管 x
和 y
比较相等,但通过 type
处理它们会导致不同的行为。但是,由于 x
是 list
的子类的一个实例,因此使用 isinstance(x,list)
会产生所需的行为并以相同的方式处理 x
和 y
。
isinstance(P, (list, tuple, set, np.ndarray))
numpy 中是否有等效于 isscalar() 的方法?是的。
>>> np.isscalar(3.1)
True
>>> np.isscalar([3.1])
False
>>> np.isscalar(False)
True
>>> np.isscalar('abcd')
True
>>> np.isscalar('abcd')
返回 True
。
return (isinstance(num, generic) or type(num) in ScalarType or isinstance(num, numbers.Number))
numpy.isscalar()
函数存在许多不可调和的设计缺陷,并且将可能在未来的某个版本中被弃用。套用 official documentation:“在几乎所有情况下,都应使用 np.ndim(x) == 0
而不是 np.isscaler(x)
,因为前者对于 0d 数组也将正确返回 true。”因此,numpy.isscalar()
的稳健前向兼容替代方案是简单地包装 numpy.ndim()
:例如,def is_scalar(obj): return np.ndim(obj) == 0
np.isscalar
令人困惑。官方文档建议在任何地方使用 np.array.ndim
,即 np.isscalar(np.array(12))
为 False,但应将其视为标量,因为 np.array(12).ndim
为 0。
虽然@jamylak 的方法更好,但这是另一种方法
>>> N=[2,3,5]
>>> P = 5
>>> type(P) in (tuple, list)
False
>>> type(N) in (tuple, list)
True
type(p) in (list, )
。
另一种替代方法(使用类名属性):
N = [2,3,5]
P = 5
type(N).__name__ == 'list'
True
type(P).__name__ == 'int'
True
type(N).__name__ in ('list', 'tuple')
True
无需导入任何东西。
这是我发现的最佳方法:检查 __len__
和 __getitem__
是否存在。
你可能会问为什么?原因包括:
流行的方法 isinstance(obj, abc.Sequence) 在某些对象上失败,包括 PyTorch 的张量,因为它们没有实现 __contains__。不幸的是,Python 的 collections.abc 中没有任何内容只检查 __len__ 和 __getitem__ ,我认为它们是类数组对象的最小方法。它适用于列表、元组、ndarray、张量等。
所以事不宜迟:
def is_array_like(obj, string_is_array=False, tuple_is_array=True):
result = hasattr(obj, "__len__") and hasattr(obj, '__getitem__')
if result and not string_is_array and isinstance(obj, (str, abc.ByteString)):
result = False
if result and not tuple_is_array and isinstance(obj, tuple):
result = False
return result
请注意,我添加了默认参数,因为大多数时候您可能希望将字符串视为值,而不是数组。对于元组也是如此。
len()
. TensorFlow 的一些令人讨厌的行为......
>>> N=[2,3,5]
>>> P = 5
>>> type(P)==type(0)
True
>>> type([1,2])==type(N)
True
>>> type(P)==type([1,2])
False
要回答标题中的问题,判断变量是否为标量的直接方法是尝试将其转换为浮点数。如果您得到 TypeError
,则不是。
N = [1, 2, 3]
try:
float(N)
except TypeError:
print('it is not a scalar')
else:
print('it is a scalar')
isinstance(np.arange(10), collections.Sequence)
时选择的答案失败。
您可以检查变量的数据类型。
N = [2,3,5]
P = 5
type(P)
它会给你输出 P 的数据类型。
<type 'int'>
这样您就可以区分它是整数还是数组。
我很惊讶这样一个基本的问题在 python 中似乎没有直接的答案。在我看来,几乎所有提议的答案都使用某种类型检查,这在 python 中通常不建议使用,而且它们似乎仅限于特定情况(它们因不同的数字类型或不是元组或列表的通用可迭代对象而失败)。
对我来说,更好的方法是导入 numpy 并使用 array.size,例如:
>>> a=1
>>> np.array(a)
Out[1]: array(1)
>>> np.array(a).size
Out[2]: 1
>>> np.array([1,2]).size
Out[3]: 2
>>> np.array('125')
Out[4]: 1
另请注意:
>>> len(np.array([1,2]))
Out[5]: 2
但:
>>> len(np.array(a))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-f5055b93f729> in <module>()
----> 1 len(np.array(a))
TypeError: len() of unsized object
>>> np.array({1:2, 3:4}).size == 1
object
的数组,其中一个元素包含字典(或生成器)。使用 np.array(list(a.items())).size
或 np.array(list(a.keys())).size
会产生不同的结果。
只需使用 size
而不是 len
!
>>> from numpy import size
>>> N = [2, 3, 5]
>>> size(N)
3
>>> N = array([2, 3, 5])
>>> size(N)
3
>>> P = 5
>>> size(P)
1
np.size(5)
和 np.size([5])
都是 == 1
,所以这不能正确区分类型(即识别标量),我认为这是目标。
{} == {{}}
。
由于 Python 中的一般准则是请求宽恕而不是许可,我认为从序列中检测字符串/标量的最 Pythonic 方法是检查它是否包含整数:
try:
1 in a
print('{} is a sequence'.format(a))
except TypeError:
print('{} is a scalar or string'.format(a))
preds_test[0] 的形状为 (128,128,1) 让我们使用 isinstance() 函数检查其数据类型 isinstance 有 2 个参数。第一个参数是数据第二个参数是数据类型 isinstance(preds_test[0], np.ndarray) 给出输出为真。这意味着 preds_test[0] 是一个数组。
不定期副业成功案例分享
list
反转为标量为假...谢谢collections.Sequence
也是字符串的 ABC,因此应该考虑到这一点。我正在使用if type(x) is not str and isinstance(x, collections.Sequence):
之类的东西。这不是很好,但它是可靠的。type
,还要检查 Python 2 上的not isinstance(x, (str, unicode))
collections.Sequence
-->collections.abc.Sequence
may 在 Python 3.9 或 3.10 中是必需的。