-1

I am trying to make up an exercise about generators, and I wanted to do it in the context of classes.

This are some of the classes I am using, skimmed down so it shows the concept and works by itself. If something doesn't make much sense on a conceptual it may be because I deleted code to make it shorter, so please spare me (for example some of this classes are way too small in the example, but it helps me show the logic I am using without showing the full implementation, I hope).

class Account():
    amount = 0
    pass

class Client:
    def __init__(self,name):
        self.nombre = name
        self.account = Account()
    pass

import random
import time

class GeneratorClass():
    def __init__(self):
        self.names = ["james", "anna"]
        self.default_client = Client(self.names[0])

@log #I decorate the class method I want to modify its behaviour with the function log, explained below
    def generatorDataClient(self, nombre = "no"):
        client = self.default_client

        amount = client.account.amount

        while True:
            amount += random.randint(0, 2000)
            yield amount
            sleep = random.choice([1, 3, 5])
            time.sleep(sleep)

for i in GeneratorClass().generatorDataClient():
    print("hello, generating, kinda")

Now I want to decorate the generatorDataClient(), for example to log calls to the function. For that I have tried several things, one of the approach is the following:

def log(func):
    def wrapper(*args, **kwargs):
        func_str = func.__name__
        args_str = '| '.join(args)
        kwargs_str = '| '.join(str(kwargs))
        s_time = time.time()
        e_time = time.time()
        duration = e_time - s_time
        print("called '%s'(%r,%r) in %d time", func_str, args_str, kwargs_str, duration)
        return (yield from func(*args, **kwargs))
    return wrapper()

Now where I am stuck:

I can do something like:

genobject3 = GeneratorClass()
generador3 = genobject3.generatorDataClient
for result in generador3:
    print("it was called ")

But I get TypeError: generatorDataClient() missing 1 required positional argument: 'self'

I have tried several other things, like decorating the instance object, and so on, and even when I get it to work, the decorator only acts once, then the generator keeps doing its thing with no modified behaviour.

Any help on how to fix this? I have been looking at other posts such as Python class method decorator with self arguments?

How to decorate a method inside a class?

decorator() got an unexpected keyword argument

But trying to emulate them is not working so far.

monkey intern
  • 705
  • 3
  • 14
  • 34

1 Answers1

1

if your code is exactly like this, then you don't want to call wrapper in log, just return the function. i.e. change it to:

def log(func):
    def wrapper(*args, **kwds):
        # ....
        return (yield from func(*args, **kwargs))
    return wrapper
Sam Mason
  • 15,216
  • 1
  • 41
  • 60
  • Your comment plus [this one](https://stackoverflow.com/a/52106179/6028947) were what I needed to make it work, so thank you very much! – monkey intern Nov 11 '19 at 11:06