0

A bit of a complex problem to describe here:

I would like to have a function AB(), which maps one input to another, through an intermediate value. More specifically, the function is made up of two function, let's call A() and B(), which both return dictionaries (ie. A[B[input]] --> result)

This is an example of my current file directory:

packageX/

    __init__.py
    get_part_of_B_expensively.py
    something_that_will_use_convert.py
    convert.py
    packageA/

        __init__.py
        get_the_entirety_of_A_expensively.py

In my convert.py I have the following:

import get_part_of_B_expensively
from packageA import get_the_entirety_of_A_expensively
dict_A = packageA.get_the_entirety_of_A_expensively()

def get_B():

    result = {}
    result = get_part_of_B_expensively() # this is a very expensive operation
    result += get_rest_of_B_inexpensively() # shorthand for adding two dictionaries
    return result # returns a dictionary

dict_B = get_B() # hence why i call it once outside, and not inside AB()

def AB(input):
    return dictA[dictB[input]]

Don't think this is proper since I can't initialize dict_B before defining get_B(), and I want AB()'s only parameter to be input, since I want to abstract its implementation. However, I introduce a few variables globally, mainly dict_B and dictA, and I'm not sure if that's the best way to do it. I can separate get_B() into its own package, but I would still be left calling them somewhere in the global frame. Not sure what the approach to this should be, I want to call A() and B(), which calls a file in the same package) as few times as possible but abstract the function AB().

zhuyxn
  • 6,671
  • 9
  • 38
  • 44
  • puzzled - what is your use-case - what is a real world example of why you think this is the design? – Jon Clements Jun 28 '12 at 05:31
  • It seems like get_B() belongs to get_part_of_B_expensively.py module. The logic of how to get B more efficiently is in convert.py, which may not be a good design. – Salil Jun 28 '12 at 06:02

1 Answers1

3

If this is all your module is doing, I wouldn't say it's that bad to keep it that way. For small scripts that are just manipulating specific data, sometimes using a global is okay, especially if you're using it as read-only. (A lot of the confusing problems with globals arise when you need to mutate them or rebind them.) There are plenty of respectable libraries that have global variables storing various sorts of global parameters, such as customization options loaded from config files, etc.

For a more heavyweight situation, if your task were more complex, you could create a class that basically does this:

class Convert(object):
    def __init__(self):
        self.A = packageA.get_the_entirety_of_A_expensively()
        self.B = getB() # or put get_B's code in here
    def AB(self, input):
        return self.A[self.B[input]]

converter = Convert()
converter.AB('blah')

This could be overkill if you just need to do one thing, but it's the way to go if you need to parameterize the operation (e.g., if you had multiple A and B dicts that you might need to operate on).

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • This looks like a good approach to me. If you don't necessarily want to use a class, you could also store the value against the function as an attribute http://stackoverflow.com/questions/338101/python-function-attributes-uses-and-abuses, but it might be better to stick to the object-oriented approach. – Aaron Newton Jun 28 '12 at 05:11