klaus
klaus

Reputation: 1227

Add custom functions to existing class in Python

Lets say I have a python program that is a black box and that acts like a processor. It reads a text file with some instruction names, parses this file and calls the functions from a class Instructions. What I want is to allow the user to create new functions in another file, and allow the processor to call these functions via the Instructions class.

Example processor code (cannot change this):

from instructions import *

instr = Instructions()
code = []
with open('program.txt') as f:
    code = f.readlines()

for line in code:
    command, args = line.split()
    # reads "command arg" and calls "instr.command(arg)"
    string_exec = 'instr.{}({})'.format(command, args)
    eval(string_exec)

Example instructions.py:

class Instructions:
    def show(self, arg):
        print(arg, end='')

Example of 'program.txt' that the processor reads to print "Hello":

show 'H'
show 'e'
show 'l'
show 'l'
show 'o'
show '\n'

I want to be able to read a file from the user with new instructions and be able to execute them in the processor.

Example of user function that also uses the instructions:

def print_line(self, args):
    for arg in args:
        instr.show(arg)
    instr.show('\n')

I want to incorporate the user functions into the class Intructions somehow, such that the processor can be able to run the following 'program.txt':

print_line 'Hello'

In short, I want to divide the Instructions functions in two files, one with some basic 'fixed' instructions, and the other with 'dynamic' functions the user defines. At the end I want to load both functions in the class Instructions.

Upvotes: 2

Views: 3593

Answers (1)

zhiwen
zhiwen

Reputation: 88

instructions.py like this:

class Instructions:
    def __init__(self):
        self._add_user_function()

    def add(self, a, b):
        return a + b

    def _add_user_function(self):
        import os
        if not os.path.exists('user_instructions.py'):
            return
        from user_instructions import UserInstructions
        self._user_instrucs = UserInstructions(self)
        for prop in dir(self._user_instrucs):
            if prop.startswith('_'):
                continue
            prop_type = type(eval("UserInstructions.%s" % prop))
            if str(prop_type).find("instancemethod") < 0:
                continue
            func_str = "def instr_custom_%s(self, *args, **kwargs):\n    return self._user_instrucs.%s(*args, **kwargs)\n    " % (prop, prop)
            exec(func_str)
            setattr(Instructions, prop, eval("instr_custom_%s" % prop))

    def show(self, arg):
        print(arg)

user_instructions.py like below:

class UserInstructions:

    def __init__(self, instr):
        self.__instr = instr

    def print_line(self, args):
        print(args)

Upvotes: 2

Related Questions