与继承的方法调用相比,具有len(),max()和min()之类的静态函数的优点 [英] The advantages of having static function like len(), max(), and min() over inherited method calls

查看:96
本文介绍了与继承的方法调用相比,具有len(),max()和min()之类的静态函数的优点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是python新手,我不确定为什么python在obj.len(上将len(obj),max(obj)和min(obj)实现为静态的类似函数(我来自Java语言)) ),obj.max()和obj.min()

与方法调用相比,具有len()...的优点和缺点(除了明显的不一致之外)是什么?

为什么guido在方法调用中选择了此选项? (如果需要,可以在python3中解决此问题,但在python3中并没有更改,因此必须有充分的理由...我希望)

谢谢!

解决方案

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

因此,为了保持一致,所有具有广泛适用性的操作都必须始终通过内置程序和/或运算符进行,并且这些内置程序的责任是查找和应用适当的特殊方法(针对一个或多个参数). ,在适用时使用替代逻辑,依此类推.

未正确应用此原理(但在Python 3中已解决不一致问题)的示例是向前推进迭代器":在2.5及更低版本中,您需要定义并调用非特殊命名的迭代器上的方法.在2.6及更高版本中,您可以使用正确的方法:迭代器对象定义__next__,新的内置next可以将其称为,并且可以应用额外的逻辑,例如提供默认值(在2.6中,为了向后兼容,您仍然可以使用旧方法,尽管在3.*中您不能再使用它了.)

另一个例子:考虑表达式x + y.如果x是某些内置类型且是您自己喜欢的新类型,如果该语言坚持将所有逻辑委派给实现加法的type(x)方法(假设该语言允许操作员重载;-),那么您将很不幸.

在Python中,+运算符(当然,如果您更喜欢内置的operator.add,当然也很相似)会尝试x的类型__add__,并且如果那个人不知道如何处理y ,然后尝试y类型的__radd__.因此,您可以定义知道如何将自己添加到整数,浮点数,复数等的类型,以及知道如何向自身添加此类内置数字类型的类型(即,可以对其进行编码,以使y + x都可以正常工作,当y是您喜欢的新类型的实例,而x是某些内置数字类型的实例时.)

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

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

i am a python newbie, and i am not sure why python implemented len(obj), max(obj), and min(obj) as a static like functions (i am from the java language) over obj.len(), obj.max(), and obj.min()

what are the advantages and disadvantages (other than obvious inconsistency) of having len()... over the method calls?

why guido chose this over the method calls? (this could have been solved in python3 if needed, but it wasn't changed in python3, so there gotta be good reasons...i hope)

thanks!!

解决方案

The big advantage is that built-in functions (and operators) can apply extra logic when appropriate, beyond simply calling the special methods. For example, min can look at several arguments and apply the appropriate inequality checks, or it can accept a single iterable argument and proceed similarly; abs when called on an object without a special method __abs__ could try comparing said object with 0 and using the object change sign method if needed (though it currently doesn't); and so forth.

So, for consistency, all operations with wide applicability must always go through built-ins and/or operators, and it's those built-ins responsibility to look up and apply the appropriate special methods (on one or more of the arguments), use alternate logic where applicable, and so forth.

An example where this principle wasn't correctly applied (but the inconsistency was fixed in Python 3) is "step an iterator forward": in 2.5 and earlier, you needed to define and call the non-specially-named next method on the iterator. In 2.6 and later you can do it the right way: the iterator object defines __next__, the new next built-in can call it and apply extra logic, for example to supply a default value (in 2.6 you can still do it the bad old way, for backwards compatibility, though in 3.* you can't any more).

Another example: consider the expression x + y. In a traditional object-oriented language (able to dispatch only on the type of the leftmost argument -- like Python, Ruby, Java, C++, C#, &c) if x is of some built-in type and y is of your own fancy new type, you're sadly out of luck if the language insists on delegating all the logic to the method of type(x) that implements addition (assuming the language allows operator overloading;-).

In Python, the + operator (and similarly of course the builtin operator.add, if that's what you prefer) tries x's type's __add__, and if that one doesn't know what to do with y, then tries y's type's __radd__. So you can define your types that know how to add themselves to integers, floats, complex, etc etc, as well as ones that know how to add such built-in numeric types to themselves (i.e., you can code it so that x + y and y + x both work fine, when y is an instance of your fancy new type and x is an instance of some builtin numeric type).

"Generic functions" (as in PEAK) are a more elegant approach (allowing any overriding based on a combination of types, never with the crazy monomaniac focus on the leftmost arguments that OOP encourages!-), but (a) they were unfortunately not accepted for Python 3, and (b) they do of course require the generic function to be expressed as free-standing (it would be absolutely crazy to have to consider the function as "belonging" to any single type, where the whole POINT is that can be differently overridden/overloaded based on arbitrary combination of its several arguments' types!-). Anybody who's ever programmed in Common Lisp, Dylan, or PEAK, knows what I'm talking about;-).

So, free-standing functions and operators are just THE right, consistent way to go (even though the lack of generic functions, in bare-bones Python, does remove some fraction of the inherent elegance, it's still a reasonable mix of elegance and practicality!-).

这篇关于与继承的方法调用相比,具有len(),max()和min()之类的静态函数的优点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆