简体   繁体   English

dict作为参数化python类的方法的替代方法是什么?

[英]What is the alternative to dict as way to parameterize python class?

I usually see the following python code around the codebase I work with: 我通常会在所使用的代码库周围看到以下python代码:

class A:
    def do_something(self):
        pass

class B:
    def do_something(self):
        pass


class C:
    _magic_dict = {'option1' : A, 'option2' : B}

   def do_something_else(self, option):
       # call some other methods, functiosn
       my_option = _magic_dict['option']()
       my_option.do_something()

       self.do_more_things(my_option)

So the basic idea is to make class C generic to A or B. Is this a common practice? 因此,基本思想是使C类对A或B通用。这是常见的做法吗? I feel like it is an overuse of dicts and the fact that everything (in this case the class) is an object that can be passed around. 我觉得这是对指令的过度使用,并且一切(在本例中为类)都是可以传递的对象。

For a more specific problem, the following example might help. 对于更具体的问题,以下示例可能会有所帮助。 There is a class responsible to take a given metric object, which in the end is a dict of objects holding the info for that type of metric. 有一个类负责获取给定的度量标准对象,该类最终是持有该度量标准类型信息的对象的字典。 And there is a statistics reporter which will take a given metric object, choose a type of data it is interested to report (one of the entries in the dict, let's say) and output that in a pretty format. 有一个统计报告器,它将使用给定的度量对象,选择要报告的数据类型(假设是dict中的一项),并以漂亮的格式输出。 So: 所以:

class FoodMetric:
    def __init__(self, path_to_my_stock_files):
        self._path = path_to_my_stock_files
        self._data = {}

    def parse(self):
        # let's assume that after parsing the files, the following data would have been obtained:
        # self.data = {'cheese' : {'cheddar' : 10, 'goat' : 20}}

class WoodFastenerMetric:
    def __init__(self, path_to_my_stock_files):
        self._path = path_to_my_stock_files
        self._data = {}

    def parse(self):
        # let's assume that after parsing the files, the following data would have been obtained:
        # self.data = {'nails' : {'round' : 10, 'oval' : 20}}

class StatsReporter:

    _magic_dict = {'food' : (FoodMetric, ['column1', 'column2'], 'cheese')
                   'wood_fastener' : (WoodFastener, ['columnA', 'columnB'], 'nail')
                  }      

    def present_data(metric_type):
        the_class, columns, data_set_name = _magic_dict(metric_type)
        metric = the_class(self._path) # assume I have the path for the files here
        metric.parse()
        print(self._convert_to_table(metric, columns, data_set_name))

I do have an alternative implementation in mind which creates C by passing an instance of either of A or B to it, therefore eliminating this dictionary lookup inside C. 我确实有一个替代实现,它通过将A或B的一个实例传递给C来创建C,因此消除了C中的字典查找。

What are other alternatives, or is the solution stated in the question a common way to solve this in python? 还有什么其他选择,还是问题中所述的解决方案是在python中解决此问题的常用方法?

PS: I hope the example make the intent more clear. PS:我希望这个例子可以使意图更加清楚。

Using the same class and method names as in the original question, and lacking any information about the actual problem being solved, I would refactor the code into the following: 使用与原始问题相同的类和方法名称,并且缺少有关要解决的实际问题的任何信息,我将代码重构为以下内容:

class C:
   def do_something_else(self):
       self.do_something()
       self.do_more_things()

    def do_something(self):
        raise NotImplementedError()

class A(C):
    def do_something(self):
        pass

class B(C):
    def do_something(self):
        pass

def make_instance(option):
    return {'option1' : A, 'option2' : B}[option]()

instance = make_instance(option)
instance.do_something_else()

With that approach, the design is clear: C implements common functionality, whereas A and B are specializations of it. 使用这种方法,设计很清楚: C实现了通用功能,而AB是其专门化功能。

The only ugly part remaining is the make_instance function, which can probably also be better, but not the way the question was stated, because it is not clear where option comes from. 剩下的唯一丑陋的部分是make_instance函数,它可能也可能更好,但是不是问题的表达方式,因为不清楚option来自何处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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