与继承的方法调用相比,具有len(),max()和min()等静态函数的优点

use*_*477 9 python language-design

我是一个python新手,我不知道为什么python实现len(obj),max(obj)和min(obj)作为一个静态函数(我来自java语言)over obj.len(),obj .max()和obj.min()

在方法调用上使用len()...有什么优点和缺点(除了明显的不一致)?

为什么guido选择了这个方法调用?(如果需要,这可以在python3中解决,但在python3中没有改变,所以必须有充分的理由......我希望)

谢谢!!

Ale*_*lli 19

最大的优点是内置函数(和运算符)可以在适当的时候应用额外的逻辑,而不仅仅是调用特殊方法.例如,min可以查看几个参数并应用适当的不等式检查,或者它可以接受单个可迭代参数并以类似方式进行; abs当在没有特殊方法的情况下调用对象时,__abs__可以尝试将所述对象与0进行比较,并在需要时使用对象更改符号方法(尽管它当前没有); 等等.

因此,为了保持一致性,所有具有广泛适用性的操作必须始终通过内置函数和/或运算符,并且这些内置函数负责查找并应用适当的特殊方法(在一个或多个参数上),使用alternate适用的逻辑,等等.

未正确应用此原则(但在Python 3中修复了不一致性)的示例是"步骤迭代器转发":在2.5及更早版本中,您需要next在迭代器上定义并调用非特殊命名的方法.在2.6及更高版本中,您可以以正确的方式执行:迭代器对象定义__next__,新的next内置可以调用它应用额外的逻辑,例如提供默认值(在2.6中,您仍然可以使用旧方法,为了向后兼容,虽然在3.*你不能再做了).

另一个例子:考虑表达式x + y.在传统的面向对象语言中(只能根据最左边的参数类型进行调度 - 如Python,Ruby,Java,C++,C#和c),如果x是某种内置类型,并且y是您自己喜欢的新类型如果语言坚持将所有逻辑委托给type(x)实现添加的方法(假设语言允许运算符重载;-) ,那么你很遗憾.

在Python中,+运算符(当然还有内置operator.add函数,如果你喜欢的话)尝试x的类型__add__,如果那个不知道该怎么做y,那么尝试y的类型__radd__.所以,你可以定义你的类型知道如何将自己添加到整数,浮点数,复杂的,等等等等,以及那些知道如何添加这样的内置数值类型本身(例如,你可以编写它,以便x + yy + x两个工作得很好,什么时候y是你喜欢的新类型x的实例,并且是一些内置数字类型的实例).

"通用函数"(如PEAK中)是一种更优雅的方法(允许基于类型组合的任何覆盖,永远不会将疯狂的单一操作集中在OOP鼓励的最左边的参数上! - )但是(a)遗憾的是它们不是接受Python 3,并且(b)他们当然要求将泛型函数表达为独立的(将函数视为属于任何单一类型的函数是绝对疯狂的,其中整个POINT是可以根据其多个参数的类型的任意组合来不同地覆盖/重载! - ).任何曾经使用Common Lisp,Dylan或PEAK编程的人都知道我在说什么;-).

因此,独立的功能和操作符只是正确,一致的方式(即使缺乏通用功能,在裸机Python中,确实消除了一些固有的优雅,它仍然是优雅和实用的合理组合! - ).

  • @sth,Python不能在RHS参数上_dispatch_ - 它可以_use内置函数或operator_来执行繁琐的工作.在C++中,如果操作者`+`是一个独立的函数,它可以根据对_statically visible_超载(又名编译时可见)类型的操作数,它只是**不能******负荷分配,也就是说,严格使用**运行时**类型的操作数来选择要执行的代码(作为成员函数可以,但仅基于**LEFT HAND SIDE**类型).对于知道调度意味着什么的读者,以及编译时和运行时类型之间的区别,没有什么不一致的! - ) (2认同)