0

Suppose I have a few functions foo_US, foo_EU, foo_JP that are very similar but have minor differences. In main() or some other function, the program is passed an argument region and one of the foo functions is called. What are some different ways to do this, and how can it be done elegantly/ efficiently. The only way I can think of right now is to define all of the foo functions separately and use if statements to check the region provided, and then call the respective function.

So something like this.

# region = 'US' # for example
if region == 'US':
    foo_US()
elif region == 'EU':
    foo_EU()
# and so on ...

However this would require that all of the foo_someRegion be declared individually.
Would it be possible to maybe declare a base class for all foo functions, and so for each specific foo function, I would only need to code the minor differences (The foo functions should have the same functionality). Furthermore, is there a way to have a base class country for example, and then have each region as a derived class so that calling foo would result in the respective foo being called? Kind of similar to having a pet base class with cat and dog sub classes where cat.speak() returns meow and dog.cry() returns woof.

Let me know if anything is unclear and any guidance is appreciated. Thank you!

1
  • Thanks everyone, I feel a bit tangled up since for each region there is a process instead of just a simple foo function. In each process there are multiple functions/steps, some which are similar across regions and some not so much. I'm trying to find a relatively elegant way to run the right process when provided with a region. Commented Oct 19, 2017 at 22:19

3 Answers 3

3

One (in my opinion) nice way to solve this problem is to use a dictionary

regionFunction = {
    'US': foo_US,
    'EU': foo_EU,
    ...
}
regionFunction(region)()

Your suggestion of creating an extra class for each region is also an option. Which approach to choose depends (again, in my opinion) on how many times you need to do this kind of thing. If this is the only time in your code where you need to call different functions depending on the region, then I would suggest using a dictionary. If you need to do it more often I suggest using classes.

Sign up to request clarification or add additional context in comments.

6 Comments

that still requires defining each one of the region functions one by one?
I think you have a typo : 'EU': foo_EU instead of 'EU': foo_US
@AsheKetchum Yes. If the functions are mostly the same you can probably extract the code they have in common into an extra function. By the way, your suggestion of writing a class for each region may be appropriate too (especially if you have this problem of having to call different functions depending on the region more than once.) - I expanded my answer to adress this
@tehforsch You bring up an interesting point. Should calling it 7 times a week because it needs to be run daily be considered "having been called more times" than running it once a week but calling 7 times during one run?
@AsheKetchum its not a matter of how frequently you call it but rather of how often this kind of idea is used in your code - if it happens more than once you might want to solve the problem once and for all by, for example, implementing a class for each region
|
1

I will make a simple example, but basically you need a class that will contain each region function as a method and then call those functions with getattr() wich allows you to call a method of a class by its name as string.

class Region(object):
    def foo_US(self):
        print('US method')

    def foo_GB(self):
        print('GB method')

    # so on...

my_region = 'foo_US'

my_region_function = getattr(Region, my_region)

my_region_function()
# >>> US method

3 Comments

I will have to think about this one. Not sure if it simplifies the problem
In order to auto-generate the functions for each region is completely dependent on the code in the functions, how much code is repeated and in which way, but can be accomplished using decorators or metaclasses
Do you have any suggestions for readings/tutorials regarding decorators and metaclasses?
1

Whether or not the foo_XY functions need to be defined separately depends on what the they do. If they are similar enough, you could write a base foo that that does something standard but can be overridden if necessary. For example:

class Region(object):

    key = None

    def foo(self):
        # Do something standard
        print(self.key)

class EURegion(Region):

    key = 'EU'

class USRegion(Region):

    key = 'US'

class WeirdRegion(Region):

    key = 'WEIRD'

    def foo(self):
        # Do something different
        print('!!!')

In your script's main function, you could retrieve the specified region dynamically using the key:

# Elided: retrieve region key from command line
regions = {cls.key: cls for cls in Region.__subclassess__()}
region = regions[key]()
region.foo()

1 Comment

Would it be correct to summarize your approach as: using derived classes of a base class to construct a dictionary mapping to achieve dynamic region execution of foo?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.