哪个接口用于初始化,哪个接口用于类方法

2024-10-02 10:28:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一些Python代码,我们希望有两个不同的接口,一个作为__init__公开,另一个通过@classmethod公开。我正在寻找哪一个界面应该放在哪里的指导

如果我们想象一个类计算不同振幅、相位和频率的正弦波之和,那么存储在对象中的是每个正弦波的数组。{}可以是:

class waveform:
    def __init__(self, amplitudes, phases, frequencies):
        self.amplitudes = amplitudes
        self.phases = phases
        self.frequencies = frequencies

为了将单个正弦波的参数分组在一起,我们添加了一个新对象,如下所示:

class singlewave:
    def __init__(self, amplitude, phase, frequency):
        self.amplitude = amplitude
        self.phase = phase
        self.frequency = frequency

然后我们可以在波形中添加一个@classmethod,使其:

class waveform:
    def __init__(self, amplitudes, phases, frequencies):
        self.amplitudes = amplitudes
        self.phases = phases
        self.frequencies = frequencies

    @classmethod
    def from_waves(cls, listOfWaves):
        amplitudes = [w.amplitude for w in listOfWaves]
        phases = [w.phase for w in listOfWaves]
        frequencies = [w.frequency for w in listOfWaves]
        return cls(amplitudes, phases, frequencies)

或者我们可以换一种方式,让waveform看起来像这样:

class waveform:
    def __init__(self, listOfWaves):
        self.amplitudes = [w.amplitude for w in listOfWaves]
        self.phases = [w.phase for w in listOfWaves]
        self.frequencies = [w.frequency for w in listOfWaves]

    @classmethod
    def from_components(cls, amplitudes, phases, frequencies):
        waves = []
        for a, p, f in zip(amplitudes, phases, frequencies):
            waves.append(singlewave(a, p, f))
        return cls(waves)

我发现第一个更优雅,因为它不需要在@classmethod中创建额外的对象,__init__的参数与对象的属性直接相关。其他人更喜欢第二个,因为__init__然后涉及到将振幅、相位和频率绑定到单个对象中

是否有一些规则或惯例表明其中一个优于另一个,或者这纯粹是个人偏好的结果

谢谢


Tags: 对象inselfforinitdefclassclassmethod
1条回答
网友
1楼 · 发布于 2024-10-02 10:28:25

我认为最好将这个问题视为类型强制,这两种表示是等价的,我希望用户看到它们是等价的

这两种方法都很好,我希望能在您的界面中找到它们 毕竟

我要做的是让__init__工作起来更愉快

class waveform:
    def __init__(self, *args, from=None):
        if from is None:
            from = self._peek_args(args)

        if from == "waves":
            ...
        elif from == "components":
           ...
        else:
           ...
    def _peek_args(self, args):
            # here you have to inspect the *args tuple
            # and guess what kind of input you got
            # rememeber to raise warnings and ValueError
            # to inform your user that he made mistakes

问题是现在你的__init__是可变的,你有 写一篇很好的文档来记录可用的内容 以及它将如何识别它

我还要提到,用户可以使用_peek_args测试输入 方法,认为它可以是一个类方法,以便更容易测试

您甚至可以扩展这个类 通过寻找__from_X方法,用户可以 当他创建子类时插入

class waveform:
    def __init__(self, *args, from=None):
        try:
            ingest = gettattr(self, '__from_{}'.format(from))
            ingest(*args)
        except AttributeError as e:
            raise ValueError("from={} is not supported".format(from))
    ...

相关问题 更多 >

    热门问题