Jônathan Dambros Jônathan Dambros - 3 months ago 8
Python Question

Update a list every time a function within a class is executexecuted with the function arguments and values

In the last 6 months, I have created many classes and function for different calculations. Now I would like to join them into a class so it could be used by other users. Like many of the methods can be performed in sequence and the sequence may require to be run multiple times for different sets of data. I would like to create a function within the main class that saves the procedure used by the user so the user could run it again without going through the whole procedure again.

Important: I would not like to change the classes that have already been implemented, but if this is the only way, no problem.

The idea would be more or less like the code represented below:

class process(object):
def __init__(self):
self.procedure = []

def MethodA(valueA):
pass

def MethodB(valueB):
pass

def UpdateProcedure(self, method, arguments, values):
# Execute this every time that MethodA or MethodB is executed.
new = {'Method':method, 'Arguments':arguments, 'Values':values}
self.procedure.append(new)


For example:

a = process.MethodA(2)
b = process.MethodB(3)

print(process.procedure)
>>> [{'Method':'MethodA', 'Arguments':['valueA'], 'Values':[2]}, {'Method':'MethodB', 'Arguments':['valueB'], 'Values':[3]}]


I have tried to use the functions
inspect.currentframe
and
__getattribute__
together, but I did not get good results.

Any ideas to help me with this issue?

Thanks

Answer

Here's how to use a decorator, per Moinuddin Quadri's suggestion:

def remember(func):
    def inner(*args, **kwargs):
        args[0].procedure.append({'method': func,
                                  'args': args,
                                  'kwargs': kwargs})
        return func(*args, **kwargs)
    return inner

class process(object):
    def __init__(self):
        self.procedure = []

    @remember
    def MethodA(self, valueA):
        pass

    @remember
    def MethodB(self, valueB):
        pass

This makes it so that every time each of these decorated methods is called, it will append their arguments to that object's procedure array. This decorator will fail on non-class methods.

Calling these commands:

p = process()

p.MethodA(1)
p.MethodB(2)
p.MethodA(3)
p.MethodB(4)
print p.procedure

will result in the following if pretty printed:

[{'args': (<__main__.process object at 0x7f25803d28d0>, 1),
  'kwargs': {},
  'method': <function MethodA at 0x7f25803d4758>},
 {'args': (<__main__.process object at 0x7f25803d28d0>, 2),
  'kwargs': {},
  'method': <function MethodB at 0x7f25803d4848>},
 {'args': (<__main__.process object at 0x7f25803d28d0>, 3),
  'kwargs': {},
  'method': <function MethodA at 0x7f25803d4758>},
 {'args': (<__main__.process object at 0x7f25803d28d0>, 4),
  'kwargs': {},
  'method': <function MethodB at 0x7f25803d4848>}]

where <__main__.process object at 0x7f25803d28d0> is the process object (self)

Read more about decorators here: https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators

Comments