如何动态调用函数

时间:2019-05-21 08:31:13

标签: python methods dynamic call

我有一个包含几个列表作为属性的类,以及几个将对象根据类型添加到特定列表的添加方法。

我的代码读取包含对象类型的csv文件,以便创建并将其添加到我的购物车。 我的问题是我正在测试对象类型以使用if elif语法调用正确的“添加”功能,但这不是很好,并且很难维护。

例如

import csv


class my_item():
    def __init__(self, name):
        self.name = name


class fruit(my_item):
    pass


class vegetable(my_item):
    pass


class meat(my_item):
    pass


class fish(my_item):
    pass


class shopping_cart():
    def __init__(self):
        self.fruits = []
        self.vegetables = []
        self.meat = []
        self.fish = []

    def add_fruit(self, o):
        self.fruits.append(o)

    def add_vegetable(self, o):
        self.vegetables.append(o)

    def add_meat(self, o):
        self.meat.append(o)

    def add_fish(self, o):
        self.fish.append(o)

    def __str__(self):
        msg = ""
        msg += "{:<25}= {:<5}\n".format('Total', str(len(self.fruits) + len(self.vegetables) + len(self.meat) + len(self.fish)))
        for attrname in vars(self):
            value = getattr(self, attrname)
            if isinstance(value, list):
                msg += "  {:<23}= {:<5}\n".format(attrname, len(value))
        return msg

def main():
    input_f = 'input.csv'
    my_cart = shopping_cart()
    with open(input_f, 'r') as i:
        rows = csv.reader(i, delimiter=';')
        for row in rows:
            item = globals()[row[0]](row[1])
            if item.__class__.__name__ == 'fruit':
                my_cart.add_fruit(item)
            elif item.__class__.__name__ == 'vegetable':
                my_cart.add_vegetable(item)
            elif item.__class__.__name__ == 'meat':
                my_cart.add_meat(item)
            else:
                my_cart.add_fish(item)
    print (my_cart)

if __name__ == '__main__':
    main()

您看到if elif块的替代内容吗?

感谢您的反馈。

2 个答案:

答案 0 :(得分:1)

我可以建议一个更简单的类设计。

  • my_item和其他类fruit, vegetable etc保留不变。被删除

  • shopping_cart被修改为self.items是一个字典,其中键是项的名称fruit, vegetables,值是这些项的列表

然后代码可能如下所示

import csv
from collections import defaultdict


class my_item:
    def __init__(self, name):
        self.name = name


class shopping_cart:

    def __init__(self):
        #Dictionary to hold items
        self.items = defaultdict(list)

    def add_item(self, type, name):

        #Increment the count of the item by 1
        self.items[type].append(name)

    def __str__(self):

        #Iterate through the dictionary and print all key/value pairs
        msg = ""
        for k,v in self.items.items():
            msg += ' {}: {} '.format(k, v)
        return msg.strip()


sc = shopping_cart()
sc.add_item('fruit', 'pomme')
sc.add_item('vegetable', 'dinde')
sc.add_item('meat', 'carotte')
sc.add_item('fish', 'saumon')

print(sc)

输出看起来像

fruit: ['pomme']  vegetable: ['dinde']  meat: ['carotte']  fish: ['saumon']

答案 1 :(得分:1)

当然,您只需要动态创建函数名称并调用它即可。 请注意,仅当my_cart具有add_{{ item name }}方法时,此方法才有效。

def main():
    input_f = 'input.csv'
    my_cart = shopping_cart()
    with open(input_f, 'r') as i:
        rows = csv.reader(i, delimiter=';')
        for row in rows:
            item = globals()[row[0]](row[1])
            item_name = item.__class__.__name__
            item_add_func_name = 'add_{}'.format(item_name)
            item_add_func = getattr(my_cart, item_add_func_name, None)
            if item_add_func and callable(item_add_func):
                item_add_func(item)
            # if item.__class__.__name__ == 'fruit':
            #     my_cart.add_fruit(item)
            # elif item.__class__.__name__ == 'vegetable':
            #     my_cart.add_vegetable(item)
            # elif item.__class__.__name__ == 'meat':
            #     my_cart.add_meat(item)
            # else:
            #     my_cart.add_fish(item)

    print (my_cart)