Unable to execute function in a list inside of a class

Viewed 157

I'm am trying to create a list of function in Python. Though my code can "see" the function and attempt to execute it, it runs in to an error saying it's missing a positional argument self.

class cpu:
    def __init__(self):
        pass

    def execute(self):
        self.instructions[0]()

    def add(self):
        print("instr add")

    def beq(self):
        print("instr beq")

    instructions = [add, beq]

cpu_ = cpu()
cpu_.execute()

Output:

Traceback (most recent call last):
  File "C:\...\src\error.py", line 17, in <module>
    cpu_.execute()
  File "C:\...\src\error.py", line 6, in execute
    self.instructions[0]()
TypeError: add() missing 1 required positional argument: 'self'
2 Answers
    ...
    self.instructions[0](self)
    ...

This seems to do the trick. I am not too sure why though.

mikey's answer is correct, but let's explain why.

As the traceback says, add needs an argument self. So whenever you call add, you need to pass at least an argument.

In python, this is done "under the carpet" by the interpreter in most typical situations. When you call a class methond inside a class, you do:

self.execute()

or when you call a method from a class instance:

cpu_.execute()

In the background, the interpreter uses self or the cpu_ instance as a first argument of the execute method.
In other terms, cpu_.execute() is a syntactic sugar for cpu.execute(cpu_), where you call a method from the class object and pass an instance of the class as first argument.

Now, when you do:

def execute(self):
    self.instructions[0]()

Here you are calling the method referred in instruction[0], but since the method is defined in a list, you cannot use the syntactic sugar. There is no self before a dot. Sure, there is self before instructions, but that one refers to the instructions list, and not to the content of the list.
So you have to explicitly provide the self argument.

self.instructions[0](self)
Related