hi everyone,

I have searched for and answer to this and cannot find any solution. So please forgive me if it is a straight forward answer!

I have a module that is imported. It has a number of subroutines inside it that need to be run, one for each year.

I want to be able to run a loop that runs each sub eg

[ YearbyYear.changes_ + str(year) + season + "_" + forecast + '(' + study + ')']
where the sub names are changes_2009summer_dev(study), changes_2009winter_dev(study), changes_2010summer_dev(study) etc etc
So year, season, and forecast are variables.

Can this be done ??? A loop is so much more elegant than 60 odd lines of if else codes.

Thanks for any help you can give.

Dani AI

Generated

Short answer: yes — as noted, you can look up a function by name on a module and call it. Two practical, maintainable patterns are shown below: (1) build the handler name and fetch it from the module with a safe check, or (2) use an explicit dispatch table (recommended when the set of handlers is finite or you want clearer control).

Example: build the name and call with safety checks.

# build a handler name from variables, then fetch and call it safely
handler_name = "changes_{0}{1}_{2}".format(year, season, forecast)

try:
    func = getattr(YearbyYear, handler_name)
except AttributeError:
    raise RuntimeError("Handler not found: %s" % handler_name)

if not callable(func):
    raise TypeError("%s exists but is not callable" % handler_name)

result = func(study)

Alternative: an explicit dispatch table (easier to test, refactor, and avoid fragile naming).

dispatch = {
    ("2009", "summer", "dev"): YearbyYear.changes_2009summer_dev,
    ("2009", "winter", "dev"): YearbyYear.changes_2009winter_dev,
    # add entries or populate programmatically
}

key = (year, season, forecast)
handler = dispatch.get(key)
if not handler:
    raise KeyError("No handler for %r" % (key,))
handler(study)

Tips and cautions

  • Prefer a dispatch table if you expect typos, refactoring, or nonstandard names; it’s explicit and testable.
  • Avoid eval; it’s fragile and risky.
  • If module names themselves are dynamic, use importlib.import_module to load by string. See the Python docs for getattr and importlib for details (getattr, importlib).
  • Add logging and unit tests that exercise every year/season/forecast combination so missing handlers are found early.

This keeps the loop concise while making failures explicit and maintainable.

Recommended Answers

All 2 Replies

This is python; of course it's possible! Here's how to retrieve a function (and call it) from a module object.

# This example imports the 'os' module, tries to retrieve the function 'getcwd' and then calls it.
import os

func = getattr(os, 'getcwd', False) #Tries to get the attribute 'getcwd' from the os module, returns False if it isn't found. Note that the getattr function can retrieve any kind of attribute from any kind of object (well, almost), given a name.

if func:
    
    func() #Outputs 'C:\\Python30'

Thankyou very much!

That was definately not something I would have found myself!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.