python - 使用 len()、max() 和 min() 等静态函数相对于继承方法调用的优势

标签 python language-design

我是 python 新手,我不确定为什么 python 在 obj.len( )、obj.max() 和 obj.min()

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

为什么 Guido 选择这个而不是方法调用? (如果需要,这可以在 python3 中解决,但它在 python3 中没有改变,所以一定有充分的理由......我希望)

谢谢!!

最佳答案

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

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

这个原则没有被正确应用(但不一致在 Python 3 中得到修复)的一个例子是“向前推进一个迭代器”:在 2.5 和更早版本中,您需要定义和调用非特殊命名的 next 迭代器上的方法。在 2.6 及更高版本中,您可以采用正确的方式:迭代器对象定义 __next__,新的 next 内置函数可以调用它应用额外的逻辑,例如提供一个默认值(在 2.6 中你仍然可以用糟糕的旧方法来实现,为了向后兼容,但在 3.* 中你不能再这样做了)。

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

在 Python 中,+ 运算符(当然还有类似的内置 operator.add,如果您喜欢的话)尝试 x 类型的 __add__,如果那个人不知道如何处理 y,则尝试使用 y 类型的 __radd__。因此,您可以定义知道如何将自己添加到整数、 float 、复数等的类型,以及知道如何将此类内置数字类型添加到自身的类型(即,您可以对其进行编码,以便 x + yy + x 都工作正常,当 y 是你喜欢的新类型的一个实例并且 x 是一些内置数字类型的实例)。

“泛型函数”(如在 PEAK 中)是一种更优雅的方法(允许基于类型组合的任何覆盖,从不疯狂的偏执狂专注于 OOP 鼓励的最左边的参数!- ),但 (a) 不幸的是,它们没有被 Python 3 接受,并且 (b) 它们当然需要将泛型函数表示为独立的(将函数视为“属于”绝对是疯狂的到任何单一类型,其中整个点是可以根据其多个参数类型的任意组合以不同方式覆盖/重载!-)。任何曾经使用 Common Lisp、Dylan 或 PEAK 编程过的人都知道我在说什么;-)。

因此,独立的函数和运算符是正确的、一致的方式(即使在基本的 Python 中缺少通用函数确实消除了固有优雅的一些部分,它仍然是优雅与实用的合理结合!-)。

关于python - 使用 len()、max() 和 min() 等静态函数相对于继承方法调用的优势,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1628222/

相关文章:

c - 是否有可能将类似 Lisp 的宏构建成命令式语言?

python - Python中元组的循环移动平均线

Python sum 与 NumPy numpy.sum

python - 命令提示符中的彩色文本在 "cls"之后但不在 "cls"之前

c# - 基于 CLR 的语言中的基于一的索引?

c# - Foreach 可以抛出 InvalidCastException 吗?

Python:在匹配行之后从文件中提取3行

python - 如何插入日期mysql python telegrambot

java - Serializable/Cloneable/... 的惯用设计在 Scala 中看起来如何?

programming-languages - 有助于编写 quines(自打印程序)的语言功能?