Python中根据字符串初始化类

Python

在算法类code中,一个非常常见的模式是读取配置,根据配置的字符串决定应该使用哪个类,即需要解决根据类名生成实例。在这个过程中,希望能够支持使用者添加自己的类,而不需要动框架代码,典型的工厂模式。

在具体到python的实现时,需要能够根据string来决定生成哪个实例,查了几种方法:

方法一:通过getattr(module_name, class_name)来生成实例,

方法二:通过eval(class_name)来生成实例,问题主要在于eval不安全

最后采用了方法一,代码如下:

factory.py

import pizza

class PizzaFactory():
    """
    Pizza factory
    """
    def __init__(self):
        """
        初始化
        """
        pass

    def create_pizza(self, module_name, name):
        """
        根据name,生成对应的pizza
        """
        module = __import__(module_name)
        pizza_class = getattr(module, name)
        return pizza_class()


class PizzaStore():
    """
    pizza store
    """
    def __init__(self):
        self._factory = PizzaFactory()

    def order_pizza(self, module_name, name):
        pizza = self._factory.create_pizza(module_name, name)
        print pizza
        pizza.make()
        pizza.box()

def read_conf(filename):
    names = []
    try:
        with open(filename, "r") as f:
            for line in f:
                module_name, class_name = line.rstrip().split()
                names.append((module_name, class_name))
    except IOError:
        sys.stderr.write("Can not find file [%s]\n" %(filename))
    return names

def main():
    """
    main function
    """
    pizza_store = PizzaStore()
    names = read_conf("pizza_conf")
    for (module_name, class_name) in names:
        pizza_store.order_pizza(module_name, class_name)


if __name__ == "__main__":
    main()

pizza.py

class Pizza():
    """
    pizza 
    """

    def make(self):
        print "I am making"

    def box(self):
        print "I am boxing"

king_pizza.py

import pizza 

class KingPizza(pizza.Pizza):
    def __init__(self):
        self._name = "My name is KingPizza"
        print self._name

queen_pizza.py

import pizza

class QueenPizza(pizza.Pizza):
    def __init__(self):
        self._name = "My name is QueenPizza"
        print self._name

pizza_conf

king_pizza  KingPizza
queen_pizza QueenPizza

Tags: