0

I know this is probably duplicate, but I couldn't find an answer that could solve my issue.

My class is defined as follows:

import time

class Destination(object):
    def __init__(self, name):
        self.name = name
        self.__idleness = time.time()
        # keeps track of the time value when object was created

    def get_idleness(self):
        now = time.time()
        return now - self.__idleness

What I want to do is to iterate a list of Destination objects based on the return value of get_idleness(), either with a for loop or with any function that uses an iterable object, for example numpy.mean() or built-in max() and min().
I have tried adding the __iter__() as:

    def __iter__(self):
        yield self.get_idleness()

but when I tried this example, output was incorrect:

dests = []
for i in range(6):
    dests.append(Destination(name="wp%s" % i))

time.sleep(1)

print max(dests)

for d in dests:
    print "%s: %s" % (d.name, d.get_idleness())

# max(dests): wp1
# printing all the values shows that wp0 should be the correct return value

EDIT: I realize my question was unclear. My end goal would be to use the value returned by self.get_idleness() when iterating over a list of Destinations. That way, no matter the iterating method, I'd compare the Destinations based on the greater idleness value.

davide m.
  • 452
  • 4
  • 19
  • 1
    So what is your problem? – a_guest Jan 20 '20 at 11:36
  • You have defined ``__iter__`` for type ``Destination``, but you call ``max`` on type ``List[Destination]``! It doesn't run what you think it does. In this case, ``max`` will use ``Destination.__lt__`` to find the largest item. – MisterMiyagi Jan 20 '20 at 11:37
  • You mean you want the object to be directly interpreted as its idleness whenever it is used in an iterator? That's probably a bad idea. Why if you just want to loop a collection of destinations? Better use `map` when you need it: `max(map(Destination.get_idleness, some_destinations))` – tobias_k Jan 20 '20 at 11:39
  • Also your type is actually not orderable since it doesn't define any comparison method. The fact that `max(dests)` works is because you are using Python 2 which has [weird behavior](https://stackoverflow.com/q/3270680/3767239) when it comes to ordering non-orderable objects. On Python 3 you would get an error. – a_guest Jan 20 '20 at 11:42
  • Can you clarify the desired behaviour? Do you want ``max`` do find the "largest" ``Destination`` instance, **or** do you want ``iter(:List[Destination])`` to yield the idleness? – MisterMiyagi Jan 20 '20 at 11:43
  • 1
    Your clarification still is unclear. The iteration and comparison are two fundamentally separate things -- ``max`` just happens to do both. So is your goal iteration or comparison? – MisterMiyagi Jan 20 '20 at 13:36

2 Answers2

0

I think you are a bit confused. If you had a list of Destination objects and wanted to get, say, the max idleness among them, you could use:

dests = [] # Your list of Destination objects
for i in range(6):
    dests.append(Destination(name="wp%s" % i))

maxIdleness = max( [d.get_idleness() for d in dests] )

You want the max (or min, mean or whatever) from a list of destinations, so that's why you create a new list. You could also create the list beforehand and reuse it for several calculations which would be more efficient:

idlenessList = [d.get_idleness() for d in dests]
maxIdleness = max(idlenessList)
minIdleness = min(idlenessList)

If you're still insterested in having a class return a custom min or max value, the following question might help you: Is there a way to return a custom value for min and max in Python?


Also note that there's an error in your code, you shouldn't use parentheses when accessing __idleness since it's an attribute and not a function:

    def get_idleness(self):
        now = time.time()
        return now - self.__idleness # not self.__idleness()
Ismael Padilla
  • 5,246
  • 4
  • 23
  • 35
0

If you want the min or max object based on its get_idleness you can do so by specifying a key function:

max(dests, key=Destination.get_idleness)
a_guest
  • 34,165
  • 12
  • 64
  • 118