Reputation: 5503
As the title asks. Python has a lot of special methods, __add__
, __len__
, __contains__
et c. Why is there no __max__
method that is called when doing max? Example code:
class A:
def __max__():
return 5
a = A()
max(a)
It seems like range()
and other constructs could benefit from this. Am I missing some other effective way to do max?¨
Addendum 1:
As a trivial example, max(range(1000000000))
takes a long time to run.
Upvotes: 2
Views: 965
Reputation: 20214
Some operations are not basic operations. Take max
as an example, it is actually an operation based on comparison. In other words, when you get a max value, you are actually getting a biggest value.
So in this case, why should we implement a specified max
function but not override the behave of comparison?
Think in another direction, what does max
really mean? For example, when we execute max(list)
, what are we doing?
I think we are actually checking list
's elements, and the max
operation is not related to list
itself at all.
list
is just a container which is unnecessary in max
operation. It is list
or set
or something else, it doesn't matter. What really useful is the elements inside this container.
So if we define a __max__
action for list
, we are actually doing another totally different operation. We are asking a container to give us advice about max value.
I think in this case, as it is a totally different operation, it should be a method of container instead of overriding built-in function's behave.
Upvotes: 1
Reputation: 152647
I have no authoritative answer but I can offer my thoughts on the subject.
There are several built-in functions that have no corresponding special method. For example:
max
min
sum
all
any
One thing they have in common is that they are reduce-like: They iterate over an iterable and "reduce" it to one value. The point here is that these are more of a building block.
For example you often wrap the iterable in a generator (or another comprehension, or transformation like map
or filter
) before applying them:
sum(abs(val) for val in iterable) # sum of absolutes
any(val > 10 for val in iterable) # is one value over 10
max(person.age for person in iterable) # the oldest person
That means most of the time it wouldn't even call the __max__
of the iterable but try to access it on the generator (which isn't implemented and cannot be implemented).
So there is simply not much of a benefit if these were implemented. And in the few cases when it makes sense to implement them it would be more obvious if you create a custom method (or property) because it highlights that it's a "shortcut" or that it's different from the "normal result".
For example these functions (min
, etc.) have O(n)
run-time, so if you can do better (for example if you have a sorted list you could access the max
in O(1)
) it might make sense to document that explicitly.
Upvotes: 3