0

(Sorry for any mistakes, this is my first post after hours of searching for a solution!!)

I have stored function names and its arguments in a txt file, and asked to call functions that carry out certain commands.

What I have done so far:

def main():
    global Pen
    filename = input("Please  enter the name of the file: ")
    plt.axis('square')
    plt.axis([-400, 400, -400, 400])
    Pen = (0, 0, False, 0)
    file = open(filename)
    commands = []
    for data in file:
        data = data.split(',')
        cs = data[0]
        ca = (data[1].rstrip('\n'))
        command = (cs, ca)
        commands.append(command)
    print(commands)
    for i in commands:
        i[0](i[1])

this is giving me a typeError: 'str' object is not callable.

How do I call the functions using a string? is there any other way to do this? (The worksheet asks me to read commands stored in an txt instruction file)

All the code for context:

from matplotlib import pyplot as plt
import math
from math import *


Pen = (0, 0, False, 0)

def main():
    global Pen
    filename = input("Please  enter the name of the file: ")
    plt.axis('square')
    plt.axis([-400, 400, -400, 400])
    Pen = (0, 0, False, 0)
    file = open(filename)
    commands = []
    for data in file:
        data = data.split(',')
        cs = data[0]
        ca = (data[1].rstrip('\n'))
        command = (cs, ca)
        commands.append(command)
    print(commands)
    for i in commands:
        i[0](i[1])


def rotate(angle):
    global Pen
    Pen = list(Pen)
    Pen[3] = Pen[3] - angle
    Pen = tuple(Pen)


def forward(distance):
    global Pen
    Pen = list(Pen)
    x = [Pen[0]]
    y = [Pen[1]]
    a = Pen[0] + (cos(radians(Pen[3])) * distance)
    b = Pen[1] + (sin(radians(Pen[3])) * distance)
    Pen[0] = a
    Pen[1] = b
    Pen = tuple(Pen)
    if Pen[2]:
        x.append(a)
        y.append(b)
        plt.plot(x, y, 'b-')


def pen(state):
    global Pen
    Pen = list(Pen)
    Pen[2] = state
    Pen = tuple(Pen)

main()

print(Pen)
plt.show()

  • Not sure if it works but you maybe could do self[variable_that_points_to_name] – Keimeno Dec 05 '19 at 18:08
  • The first thing that comes to mind is using the eval() command. Typically if your function is already defined in python but you are passing around a string version of the function name, you can run eval on the string and Python will be able to run the function and you can pass parameters. See more details here: https://stackoverflow.com/questions/7719466/how-to-convert-a-string-to-a-function-in-python. However, I think what you are asking is even more complicated in the sense that the whole function is a string that you want to use at runtime. – rmilletich Dec 05 '19 at 18:10
  • 1
    A straightforward way would be to use `globals()[function_name_as_string]()` – juanpa.arrivillaga Dec 05 '19 at 18:45
  • Is this homework? This seems like a bizarre assignment. Also you didn’t actually share any of the data. See: [mcve]. – AMC Dec 05 '19 at 21:33
  • @AlexanderCécile yh, they asking us to write a simple turtle drawing program. [link](https://drive.google.com/file/d/1VrxQZqoGbSZTImM5HxFDT6O8kJkSsXgh/view?usp=sharing)`here` is the data – muwahhid Dec 06 '19 at 14:44

2 Answers2

0

When you are iterating over the commands tuple to call it's items you may want to just check to see if your i[0] is equal to the string names of the functions then just call that function if the equality is true.

for i in commands:
    if i[0] == 'functionName':
        functionName(i[1])
0

Make your functions slightly differently, following this template, and you'll be able to call them from a string.

TEMPLATE:

class MyClass:
    @staticmethod
    def return_double(x):
        return x*2

method_name = 'return_double'
my_cls = MyClass()

method = getattr(my_cls, method_name)

method(2)
Out[19]: 4

IN YOUR CASE:

class MyClass:
    @staticmethod
    def main():
        global Pen
        filename = input("Please  enter the name of the file: ")
        plt.axis('square')
        plt.axis([-400, 400, -400, 400])
        Pen = (0, 0, False, 0)
        file = open(filename)
        commands = []
        for data in file:
            data = data.split(',')
            cs = data[0]
            ca = (data[1].rstrip('\n'))
            command = (cs, ca)
            commands.append(command)
        print(commands)
        for i in commands:
            i[0](i[1])

method_name = 'main'
my_cls = MyClass()

method = getattr(my_cls, method_name)

method()
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
  • 1
    A class with a bunch of staticmethods shouldn't be a class at all. Just use a regular old container, even a `dict`, or maybe a `SimpleNamespace`. Honestly, the module itself is just a namespace, which can be accessed directly from `globals()` – juanpa.arrivillaga Dec 05 '19 at 18:41