Home > Net >  Python dynamic function & parameters call - str object is not callable
Python dynamic function & parameters call - str object is not callable

Time:06-26

I´m trying to come up with a dynamic function calling system. I have a database with a bunch of differents levels: Decision Evaluator > Function (response curve) parameters > Inputs. Choosing a Decision Evaluator may call 10 different functions but only 5 inputs, treated differently through the parameters. So it would be way easier to have a dynamic system rather than create all the sub-calls for each main level.

In the test below, I can dynamically call a lower-level function from an upper level ('test'). When I try to pass arguments, I get the error 'str' object is not callable. Here's the trace:

C:\ProgramData\Anaconda3\lib\site-packages\openpyxl\worksheet\_reader.py:312: UserWarning: Data Validation extension is not supported and will be removed
  warn(msg)
Traceback (most recent call last):
  File "C:\Users\*\considerations.py", line 28, in <module>
    ich.dynamic_call(abcd_3(show_test))
TypeError: 'str' object is not callable
init ICH...
oouh weee look at me

Process finished with exit code 1

considerations.py:

from input_clearing_house import InputClearingHouse
import pandas as pd

inputs = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='Inputs')
considerations = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='Considerations')
decision_score_evaluator = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='DecisionScoreEvaluator')
decision_maker = pd.read_excel(r'AXIS_DB.xlsx', sheet_name='DecisionMaker')

considerations = pd.merge(considerations, inputs, on='input_name')
# print(considerations)

ich = InputClearingHouse()

abcd_2 = 'test'
abcd_3 = 'multi21'
show_test = 'dynamite'

ich.dynamic_call(abcd_2)
ich.dynamic_call(abcd_3(show_test))

input_clearing_house.py:

import math


class InputClearingHouse:
    def __init__(self):
        print('init ICH...')

    def dynamic_call(self, name, *args, **kwargs):
        call_fct = f'{name}'
        if hasattr(self, call_fct) and callable(func := getattr(self, call_fct)):
            func(*args, **kwargs)

    def test(self):
        print("oouh weee look at me")

    def multi21(self, *args):
        for arg in args:
            print(arg)

    def distance_to_target(self, source: tuple, target: tuple) -> float:
        return math.sqrt((source[0] - target[0]) ** 2   (source[1] - target[1]) ** 2)

    def my_endurance(self, current: int, maximum: int) -> float:
        return current / maximum

CodePudding user response:

abcd_3(show_test) is trying to use abcd_3 as a function, but it's a string that names a function.

ich.dynamic_call() expects the name and arguments of the function to call to be separate arguments, so you should use

ich.dynamic_call(abcd_3, show_test)

CodePudding user response:

Your dynamic_call() method already copes with variable numbers of arguments.

I think you just meant to add arguments:

ich.dynamic_call(abcd_3, show_test)
  • Related