Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Function prints none instead of printing what I want it to print in decorators in Python

I am studying on decorators in Python. I was trying to use the decorators with arguments. I’m having a problem with the decorators. I defined two inner function in the default decorator function. It returns none when I use it as below:

def prefix(write: bool = False):
    def thread(func):
        def wrapper(*args, **kwargs):
            t1 = Thread(target=func, args=args, kwargs=kwargs)
            t1.start()
            if write:
                print("write parameter is true.")
        return wrapper
    return thread


@prefix(write=True)
def something(x):
    return x + x


print(something(5))

As you see, I defined two different functions named prefix and something. If the write parameter is true, it prints the string. But something function is printing "None" instead of printing 5 + 5.

What’s wrong?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Well, your wrapper() function doesn’t have a return statement, so it will always return None.

Furthermore, how would you expect it to print 5 + 5 (or rather, the result thereof) when that may not have been computed yet, considering you’re starting a new thread to do that and never do anything with the return value of func at all?

IOW, if we expand your example a bit:

import time
from threading import Thread


def prefix(write: bool = False):
    def thread(func):  # <- this function replaces `something`
        def wrapper(*args, **kwargs):
            t1 = Thread(target=func, args=args, kwargs=kwargs)
            t1.start()
            if write:
                print("write parameter is true.")
            return "hernekeitto"

        return wrapper

    return thread


@prefix(write=True)
def something(x):
    print("Computing, computing...")
    time.sleep(0.5)
    print("Hmm, hmm, hmm...")
    time.sleep(0.5)
    print("Okay, got it!")
    return x + x


value = something(9)
print("The value is:", value)

This will print out

Computing, computing...
write parameter is true.
The value is: hernekeitto
Hmm, hmm, hmm...
Okay, got it!

As you can see, the thread’s first print() happens first, then the write print, then the value print, and then the rest of what happens in the thread. And as you can see, we only know what x + x is after "Okay, got it!", so there’s no way you could have returned that out of wrapper() where "hernekeitto" is returned.

See futures (or the equivalent JavaScript concept promises) for a "value that’s not yet ready":

import time
from concurrent.futures import Future
from threading import Thread


def in_future(func):
    def wrapper(*args, **kwargs):
        fut = Future()

        def func_wrapper():
            # Wraps the threaded function to resolve the future.
            try:
                fut.set_result(func(*args, **kwargs))
            except Exception as e:
                fut.set_exception(e)

        t1 = Thread(target=func_wrapper)
        t1.start()
        return fut

    return wrapper


@in_future
def something(x):
    print("Computing, computing...")
    time.sleep(0.5)
    print("Hmm, hmm, hmm...")
    time.sleep(0.5)
    print("Okay, got it!")
    return x + x


value_fut = something(9)
print("The value is:", value_fut)
print("Waiting for it to be done...")
print("Here it is!", value_fut.result())

This prints out

Computing, computing...
The value is: <Future at 0x... state=pending>
Waiting for it to be done...
Hmm, hmm, hmm...
Okay, got it!
Here it is! 18

so you can see the future is just a "box" where you’ll need to wait for the actual value to be done (or an error to occur getting it).

Normally you’d use futures with the executors in concurrent, but the above is an example of how to do it by hand.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading