我是 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 + y
和 y + 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/