所以 .loc 和 .iloc 不是你的典型函数。他们以某种方式使用 [ 和 ] 来包围参数,以便它与普通数组索引相当。但是,我从未在另一个库中看到过这个(我可以想到,也许 numpy 就像我正在空白的东西),而且我不知道它在技术上是如何工作的/在 python 代码中定义的。
在这种情况下,括号是否只是函数调用的语法糖?如果是这样,那么如何使任意函数使用括号而不是括号?否则,它们的使用/定义 Pandas 有什么特别之处?
所以 .loc 和 .iloc 不是你的典型函数。他们以某种方式使用 [ 和 ] 来包围参数,以便它与普通数组索引相当。但是,我从未在另一个库中看到过这个(我可以想到,也许 numpy 就像我正在空白的东西),而且我不知道它在技术上是如何工作的/在 python 代码中定义的。
在这种情况下,括号是否只是函数调用的语法糖?如果是这样,那么如何使任意函数使用括号而不是括号?否则,它们的使用/定义 Pandas 有什么特别之处?
注意:这个答案的第一部分是我对另一个问题的回答的直接改编,在重新打开这个问题之前已经回答了这个问题。我在第二部分扩展了“为什么”。
所以 .loc 和 .iloc 不是你的典型函数
事实上,它们根本不是函数。我会用 , 来做例子loc
,iloc
是类似的(它使用不同的内部类)。检查loc
实际情况的最简单方法是:
import pandas as pd
df = pd.DataFrame()
print(df.loc.__class__)
哪个打印
<class 'pandas.core.indexing._LocIndexer'>
这告诉我们这df.loc
是一个_LocIndexer
类的实例。该语法loc[]
源自_LocIndexer
定义__getitem__
和__setitem__
*的事实,这是每当您使用方括号语法时 python 调用的方法。
所以是的,从技术上讲,括号是某些函数调用的语法糖,而不是您认为的函数(当然,python 设计成这种方式的原因有很多,我不会在这里详细介绍,因为 1)我我不够专业,无法提供详尽的答案,并且 2)网上有很多关于这个主题的更好的资源)。
*从技术上讲,它_LocationIndexer
是定义这些方法的基类,我在这里简化了一点
为什么 Pandas 在 .loc 和 .iloc 中使用方括号?
我在这里进入推测区域,因为我找不到任何明确谈论 Pandas 中的设计选择的文档,但是:我认为选择方括号至少有两个很好的理由。
第一个也是最重要的原因是:你根本不能用方括号表示法来处理函数调用,因为分配给函数调用是 python 中的语法错误:
# contrived example to show this can't work
a = []
def f():
global a
return a
f().append(1) # OK
f() = dict() # SyntaxError: cannot assign to function call
对“函数”调用使用圆括号,调用底层__call__
方法(请注意,任何定义了__call__
is 的类callable
,所以“函数”调用是一个不正确的术语,因为 python 不关心某个东西是函数还是只是表现得像一个)。
相反,使用方括号可以调用__getitem__
或__setitem__
取决于调用发生的时间(__setitem__
如果它在赋值运算符的左侧,__getitem__
在任何其他情况下)。无法通过函数调用来模仿这种行为,您需要一个 setter 方法来修改数据框中的数据,但在赋值操作中仍然不允许这样做:
# imaginary method-based alternative to the square bracket notation:
my_data = df.get_loc(my_index)
df.set_loc(my_index, my_data*2)
这个例子让我想到了第二个原因:一致性。您可以通过方括号访问 DataFrame 的元素:
something = df['a']
df['b'] = 2*something
使用时,loc
您仍在尝试引用 DataFrame 中的某些项目,因此使用相同的语法而不是要求用户使用一些 getter 和 setter 函数更加一致(我相信它也是“更多的 Pythonic”,但是这是一个模糊的概念,我宁愿远离)。
在封面下,两者都在使用__setitem__
和__getitem__
功能。