用super做管道?

2024-09-30 01:35:22 发布

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

我在考虑如何使用super在python中创建管道。我必须对一个流进行一系列的转换,我认为这样做的一个好方法是:

class MyBase(object):
    def transformData(self, x):
        return x

class FirstStage(MyBase):

    def transformData(self, x):
        y = super(FirstStage, self).transformData(x)
        return self.__transformation(y)

    def __transformation(self, x):
        return x * x

class SecondStage(FirstStage):

    def transformData(self, x):
        y = super(SecondStage, self).transformData(x)
        return self.__transformation(y)

    def __transformation(self, x):
        return x + 1

这是我想要的,但有一个潜在的重复。如果我有N个stage,那么我将有N个相同的transformData方法,其中唯一要更改的是当前类的名称。你知道吗

有办法去掉这个样板吗?我尝试了一些方法,但结果只能证明我还没有完全理解super的工作原理。你知道吗

我想要的是只定义方法__transformation,然后自然地继承一个transformData方法,该方法将在MRO中出现,调用该类transformData方法,然后对结果调用当前类__transformation。是否有可能或者必须为每个子类定义一个新的相同的transformData?你知道吗


我同意这是一个糟糕的管道实施方式。这可以通过更简单(更清晰)的方案来实现。我认为这是我可以对现有模型做的最少修改,以便在不太修改代码的情况下从现有类中获取管道。我同意这不是最好的办法。这将是一个骗局,而骗局应该避免。我还认为这是更好地理解super工作原理的一种方式。你知道吗

布尤特。出于好奇。。。在上面的方案中不需要transformData重复就可以做到吗?这是一个真正的疑问。继承transformData有什么诀窍吗?它的super调用被更改为在当前类上调用?你知道吗

这将是一个非常不清楚,不可读,聪明的屁股骗局。我知道。但有可能吗?你知道吗


Tags: 方法selfreturn管道defclass原理super
2条回答

我不认为对管道使用继承是正确的方法。你知道吗

相反,在这里用“简单”的例子和参数化的例子(一个使用__call__魔术方法的类,但是返回一个closured函数也可以,或者甚至通过eval“JITing”一个)。你知道吗

def two_power(x):
    return x * x

def add_one(x):
    return x + 1

class CustomTransform(object):
    def __init__(self, multiplier):
        self.multiplier = multiplier

    def __call__(self, value):
        return value * self.multiplier

def transform(data, pipeline):
    for datum in data:
        for transform in pipeline:
            datum = transform(datum)
        yield datum

pipe = (two_power, two_power, add_one, CustomTransform(1.25))
print list(transform([1, 2, 4, 8], pipe))

将输出

[2.5, 21.25, 321.25, 5121.25]

问题是在这里使用继承在面向对象编程方面是相当奇怪的。在定义类时,您真的需要定义整个转换链吗?你知道吗

但最好还是忘了面向对象编程,这个任务不是面向对象编程的。只需定义转换函数:

def get_pipeline(*functions):
    def pipeline(x):
        for f in functions:
            x = f(x)
        return x
    return pipeline

p = get_pipeline(lambda x: x * 2, lambda x: x + 1)

print p(5)

更简短的版本如下:

def get_pipeline(*fs):
    return lambda v: reduce(lambda x, f: f(x), fs, v)

p = get_pipeline(lambda x: x * 2, lambda x: x + 1)
print p(5)

这是一个面向对象的解决方案。与前一个相比,它相当笨拙:

class Transform(object):
    def __init__(self, prev=None):
        self.prev_transform = prev

    def transformation(self, x):
        raise Exception("Not implemented")

    def transformData(self, x):
        if self.prev_transform:
            x = self.prev_transform.transformData(x)
        return self.transformation(x)

class TransformAdd1(Transform):
    def transformation(self, x):
        return x + 1

class TransformMul2(Transform):
    def transformation(self, x):
        return x * 2

t = TransformAdd1(TransformMul2())
print t.transformData(1) # 1 * 2 + 1

相关问题 更多 >

    热门问题