简体   繁体   中英

Storing Functions in Dictionary [Python]

I'm currently building an application where I need to iterate over a series of steps that do largely the same thing, save a very small amount of code (~15 lines). The number of steps will vary depending on how the project is configured, so it seems kind of silly for me to create a separate function for each potential instance.

In JavaScript, I would do something like this:

var switches = [true, true, false, true];

var holder = {
    0: function() { /* do step0 */ }
    1: function() { /* do step1 */ }
    2: function() { /* do step2 */ }
    3: function() { /* do step3 */ }
    // ...etc...
}

for (var i = 0; i < switches.length; i++)
    if (switches[i])
        holder[i]();

Is there a way to do something similar to this in python? The only thing I can think of is something like this:

switches = [True, True, False, True]

class Holder(object):
    @staticmethod
    def do_0():
        # do step0

    @staticmethod
    def do_1():
        # do step 1

    # ...etc...

    def __repr__(self):
        return [self.do_0, self.do_1, ...]

for action in Holder:
    action()

This just seems terribly inefficient if I have any significant number of steps. Is there any better way to go about this?

You can do this as follows:

# define your functions
def fun1():
    print("fun1")

def fun2():
    print("fun2")

def fun3():
    print("fun3")


switches = [True, False, True];

# put them in a list (list makes more sense than dict based on your example)
func_list = [fun1, fun2, fun3]

# iterate over switches and corresponding functions, and execute 
# functions when s is True    
for s,f in zip(switches, func_list):
    if s: f() 

This is one way only. There are many others. eg using lambdas, dict as you wanted, etc.

To use lambdas if your functions are one line only, you can do:

func_list = [lambda: print("lambda1"), 
             lambda: print("lambda2"), 
             lambda: print("lambda1")]

It looks like there isn't a way to do this in Python, a design decision made intentionally since it was dismissed as un-Pythonic. Oh well, it looks like I'm stuck defining the methods and then manually adding them to a list to iterate through.

Source: https://softwareengineering.stackexchange.com/a/99245

- Your functions don't need to be enveloped in a utility class.
- I don not see how the two blocks of code differ in efficiency.
- You can use enumerate and lambdas to simplify your code.

Simplified Code

d = {0: lambda: 'Performing Step 0',
     1: lambda: 'Performing Step 1',
     2: lambda: 'Performing Step 2',
     3: lambda: 'Performing Step 3',
     4: lambda: 'Performing Step 4'}

for index, switch in enumerate([1, 0, 1, 1, 0]):
    if switch == 1: d[index]() 

I typically go about this like the following. I like this approach, because it adds a minimum of typing overhead to the code, and if you write an additional method later on, nothing needs to be modified elsewhere in the file.

def steptest0():
    code
def steptest1():
    code
def steptest2():
    code

...

tests = filter(lambda x: x.startswith('steptest'),
               dir())
for t in tests: eval(t + '()')

Every method is already put into a dictionary automatically in Python, and dir() lets us access that.

Disclaimer. There are multiple alarm bells starting to go off in the head of the average pedestrian zealot at the sight of "eval" and some may even have seizures. Let them guard themselves from eval by using a reflection mechanism instead (which might make it less readable, but still worth it, as they can't be accused of using "eval").

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM