关于编码风格:带有外部函数的Python工厂方法

Python factory method with external function

我已经阅读过这个关于工厂方法的讨论,并且有一个备用的构造函数用例。

我的班级如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Foo(object):
    def __init__(self, bar):
        self.bar = bar

    @classmethod
    def from_data(cls, datafile):
        bar = datafile.read_bar()
        # Now I want to process bar in some way
        bar = _process_bar(bar)
        return cls(bar)

    def _process_bar(self, bar)
        return bar + 1

我的问题是,如果一个@classmethod工厂方法想要在其代码中使用一个函数,那么该函数(_proces_bar应该是:

  • 一个@classmethod,这看起来有点奇怪,因为你不会把它叫做Foo._process_bar()
  • Foo之外但在同一个.py文件中的一种方法。我会同意的,但看起来有点奇怪。这些方法是否始终可用于Foo的实例,而不管它是如何实例化的?(例如,如果它被保存到一个泡菜中,然后重新加载呢?可能类外的方法将不可用!)
  • 一个@staticmethod?(见1)。这看起来很奇怪)
  • 还有别的吗?(但不是这个!)

  • "正确的解决方案"取决于您的需求…

    • 如果函数(_process_bar需要访问类Foo或当前的子类……,那么您需要一个classmethod,它应该被称为cls._process_bar(),而不是Foo._process_bar()

    • 如果函数不需要访问类本身,但您仍然希望能够在子类中重写它(iow:您希望基于类的多态性),那么您需要一个staticmethod

    • 否则你只需要一个简单的函数。这个函数的代码存在的地方是不相关的,而您的导入问题是其他方面的。

    此外,您可能(或不,取决于具体的用例)希望使用回调函数(可能带有默认值)来实现更大的灵活性,例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def process_bar(bar):
       return bar + 1

    class Foo(object):
        @classmethod
        def from_data(self, datafile, processor=process_bar):
            bar = datafile.read_bar()
            bar = processor(bar)
            return cls(bar)