2

I'm going through a Python OOPs book by Dusty Phillips. I fail to understand a particular program in the book, chapter 7 - Python Object-oriented Shortcuts. The extended version of the code is available here

Although the program comes under the topic Functions are objects too, the provided program also uses a strange code, which i feel, more of imply the opposite (using objects as functions).

I have pointed out the line in the code where i have the doubt. How is that variable callback of TimedEvent used like a function Timer class ? What is going on here in this part.

import datetime
import time

class TimedEvent:
    def __init__(self, endtime, callback):
        self.endtime = endtime
        self.callback = callback

    def ready(self):
        return self.endtime <= datetime.datetime.now()

class Timer:
    def __init__(self):
        self.events = []

    def call_after(self, delay, callback):
        end_time = datetime.datetime.now() + \
        datetime.timedelta(seconds=delay)
        self.events.append(TimedEvent(end_time, callback))

    def run(self):
        while True:
            ready_events = (e for e in self.events if e.ready())
            for event in ready_events:
                event.callback(self)               ----------------> Doubt
                self.events.remove(event)
            time.sleep(0.5)
3
  • 2
    Well how is callback initialised? You don’t show that part. Is a function assigned to it? Or something else? Commented Jul 30, 2020 at 17:31
  • You can see it in the init of TimedEvent. But I was wondering how its being used for calling other objects! And by the way, the full code is provided in a link as well. The only 'callback' in the code is the one I mentioned. Commented Jul 30, 2020 at 17:39
  • That’s insufficient, because we don’t know how call_after is called! Looking at the linked code, call_after is always invoked with a regular function for callback. So callback … just contains a function. Commented Jul 30, 2020 at 17:40

2 Answers 2

5

Both are true

  • functions are objects: do a dir(f) on a function to view its attributes
  • objects can be used as functions: just add __call__(self, ...) method and use the object like a function.

In general things that can be called using a syntax like whatever(x, y, z) are called callables.

What the example is trying to show is that methods are just object attributes that are also callables. Just like you can write obj.x = 5, you can also write obj.f = some_function.

Sign up to request clarification or add additional context in comments.

8 Comments

Are they really methods? Not just functions stored as attributes?
Python's glossary defines "method" as "A function which is defined inside a class body. [...]", and here they're top-level functions.
@superbrain: that's complicated. Functions become methods when they are looked up using object.f. A method is a function that has already been passed the self argument (that's the important part of the definition, doesn't matter where they are defined). Look into the descriptor protocol on how that happens. Descriptors are really interesting, they explain various aspects of python.
self is written explicitly in the code, but it's not passed by the programmer, it's passed by the interpreter. That happens using the descriptor protocol when the function is looked up using the dot. But, it's really complicated, if you are interested look into descriptors.
Just to be sure: You've seen that they have functions like this, which are stored as attribute with self.callback = callback (where the right-hand callback is that function), and then later called?
|
1

Yes, that example indeed shows that functions are object. You can assign an object to the callback attribute and this tries to show that the object you assign to callback can be a function.

class TimedEvent:
    def __init__(self, endtime, callback):
        self.endtime = endtime
        self.callback = callback

What is missing to make it clear is the initialization. You could, for example, do this:

def print_current_time():
    print(datetime.datetime.now().isoformat())

event = TimedEvent(endtime, print_current_time)
event.callback()

This will actually call print_current_time, because event.callback is print_current_time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.