TL;DR: range
s have __getitem__
, and __len__
, while map
s don't.
细节
我假设创建新数据框列的语法在某种程度上是语法糖Pandas.DataFrame.插入 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.insert.html,它作为参数value
a
标量、级数或类数组
鉴于此,问题似乎简化为“为什么 pandas 将列表和范围视为类似数组,而不是地图?”
See: numpy:“类似数组”对象的正式定义? https://stackoverflow.com/questions/40378427/numpy-formal-definition-of-array-like-objects.
如果您尝试在范围之外创建一个数组,它会很好地工作,因为范围足够接近类似数组,但您不能使用映射来做到这一点。
>>> 将 numpy 导入为 np
>>> foo = np.array(范围(10))
>>> bar = np.array(map(lambda x: x + 1, range(10))
>>> 富
数组([0,1,2,3,4,5,6,7,8,9])
>>> 酒吧
array(, dtype=object)
map
不是“类似数组”,而range
is.
进一步研究PyArray_GetArrayParamsFromObject https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/ctors.c#L1538,在链接的答案中提到,函数末尾调用 PySequence_Check。该代码是 python 代码,Stack Overflow 上对此有很好的讨论:Python的序列协议是什么? https://stackoverflow.com/questions/43566044/what-is-pythons-sequence-protocol
.
早些时候,在相同的文件 https://github.com/numpy/numpy/blob/master/numpy/core/src/multiarray/ctors.c#L812, 它说:
/*
* PySequence_Check detects whether an old type object is a
* sequence by the presence of the __getitem__ attribute, and
* for new type objects that aren't dictionaries by the
* presence of the __len__ attribute as well. In either case it
* is possible to have an object that tests as a sequence but
* doesn't behave as a sequence and consequently, the
* PySequence_GetItem call can fail. When that happens and the
* object looks like a dictionary, we truncate the dimensions
* and set the object creation flag, otherwise we pass the
* error back up the call chain.
*/
这似乎是“类数组”的主要部分 - 任何具有getitem and len类似于数组。range
两者都有,同时map
两者都没有。
自己尝试一下吧!
__getitem__
and __len__
是创建序列所必需且充分的,因此可以让列按您的意愿显示,而不是作为单个对象显示。
尝试这个:
class Column(object):
def __len__(self):
return 5
def __getitem__(self, index):
if 0 <= index < 5:
return index+5
else:
raise IndexError
col = Column()
a_col = np.array(col)
- 如果你两者都没有
__getitem__()
or __len()__
,numpy 会为你创建一个数组,但它会包含其中的对象,并且不会为你迭代。
- 如果您同时拥有这两种功能,它就会按照您想要的方式显示。
(感谢 user2357112 纠正我。在一个稍微简单的例子中,我认为__iter__
被要求。它不是。这__getitem__
不过,函数确实需要确保索引在范围内。)