将字典用于控制方法的执行顺序

34 阅读2分钟

我们有一个包含多个方法的Population类。根据输入,我们希望以给定的顺序对Population类的实例运行这些方法。

我们尝试使用以下代码来实现:

huake_00066_.jpg

stuff = input(" enter stuff ")

dico = {'stuff1':functionA, 'stuff2':functionC, 'stuff3':functionB, 'stuff4':functionD}
http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
dico[stuff]()

但是,我们遇到的问题是functionA、functionB等是方法而不是函数。我们希望使用如下代码:

order_type = 'a'
class Population (object):
    def __init__(self,a):
        self.a = a

    def method1 (self):
        self.a = self.a*2
        return self

    def method2 (self):
        self.a += 2
        return self

    def method3 (self,b):
        self.a = self.a + b
        return self

if order_type=='a':
    order = {1:method1, 2:method2, 3:method3}
elif order_type=='b':
    order = {1:method2, 2:method1, 3:method3}
else :
    order = {1:method3, 2:method2, 3:method1}

my_pop = Population(3)

while iteration < 100:
    iteration +=1
    for i in range(len(order)):
        method_to_use = order[i]
        my_pop.method_to_use() # 但显然这是行不通的!

希望我已经把我的问题表达得很清楚了!
请注意,我的一个方法需要两个参数。

2、解决方案 有以下三种方法可以解决这个问题:

方法一:使用getattr

order = {1:'method1', 2:'method2', 3:'method3'} #values are strings
...
method_to_use = order[i]
getattr(mypop, method_to_use)()

方法二:将实例显式地作为第一个参数传递

method_to_use = order[i]
method_to_use(my_pop)

完整的有效代码如下:

order_type = 'a'
class Population (object):
    def __init__(self,a):
        self.a = a

    def method1 (self):
        self.a = self.a*2
        return self

    def method2 (self):
        self.a += 2
        return self

    def method3 (self):
        self.a = 0
        return self

if order_type=='a':
    order = [Population.method1, Population.method2, Population.method3]
elif order_type=='b':
    order = [Population.method2, Population.method1, Population.method3]
else :
    order = [Population.method3, Population.method2, Population.method1]

my_pop = Population(3)

while iteration < 100:
    iteration +=1
    for method_to_use in order:
        method_to_use(my_pop)

如果你想传递多个参数,只需使用*args语法:
if order_type=='a':
    order = [Population.method1, Population.method2, Population.method3]
    arguments = [(), (), (the_argument,)]
elif order_type=='b':
    order = [Population.method2, Population.method1, Population.method3]
    arguments = [(), (), (the_argument,)]
else :
    order = [Population.method3, Population.method2, Population.method1]
    arguments = [(the_argument, ), (), ()]

my_pop = Population(3)

while iteration < 100:
    iteration +=1
    for method_to_use, args in zip(order, arguments):
        method_to_use(my_pop, *args)

()是一个空元组,因此*args将扩展为没有额外的参数,而(the_argument,)是一个1元素元组,它将参数传递给方法。

方法三:使用operator.methodcaller

from operator import methodcaller
method_to_use = methodcaller('method' + str(i))
method_to_use(my_pop)