python - 代码味道 - if/else 构造

标签 python oop code-duplication

我有一个包含 9 个元素的列表。前三个代表位置,下一个速度,下一个力。

有时我需要来自阵列的力,有时需要速度,有时需要位置。

于是我写了一个函数如下:

def Extractor(alist,quantity):

    if quantity=='positions':
        x = alist[0]
        y = alist[1]
        z = alist[2]
        return (x,y,z)

    elif quantity=='velocities':
        vx = alist[3]
        vy = alist[4]
        vz = alist[5]
        tot_v = np.sqrt(vx**2 + vy**2 + vz**2)
        return (vx,vy,vz,tot_v)

    elif quantity=='forces':
        fx = alist[6]
        fy = alist[7]
        fz = alist[8]
        tot_f = np.sqrt(fx**2 + fy**2 + fz**2)
        return (fx,fy,fz,tot_f)
    else:
        print "Do not recognise quantity: not one of positions, velocities, force"

但是,由于代码重复,这对我来说似乎是一种巨大的代码味道。有没有更好、更 pythonic 的方法来做到这一点?我对 OOP 很陌生,但我可以使用某种利用多态性的类继承吗?

最佳答案

您的方法违反了 Single Responsibility Principle .考虑像这样拆分它:

def positionExtractor(alist):
    return tuple(alist[0:3])

def velocityExtractor(alist):
    velocity = tuple(alist[3:6])
    return velocity + (np.sqrt(sum(x**2 for x in velocity)),)

def forcesExtractor(alist):
    forces = tuple(alist[6:9])
    return forces + (np.sqrt(sum(x**2 for x in forces)),)

你可以把它们放在字典里:

extractors = {
    'position' : positionExtractor,
    'velocity' : velocityExtractor,
    'forces' : forcesExtractor}

并使用:

result = extractors[quantity](alist)

这是一个继承的例子。不过,对于这样一个简单的任务来说,它似乎是过度设计的:

import numpy as np

class Extractor:
    def extract(self, alist):
        raise NotImplementedError()

class IndexRangeExtractor(Extractor):
    def __init__(self, fromIndex, toIndex):
        self.fromIndex = fromIndex
        self.toIndex = toIndex

    def extract(self, alist):
        return tuple(alist[self.fromIndex:self.toIndex])

class EuclideanDistanceExtractorDecorator(Extractor):
    def __init__(self, innerExtractor):
        self.innerExtractor = innerExtractor

    def extract(self, alist):
        innerResult = self.innerExtractor.extract(alist)
        distance = np.sqrt(sum(x**2 for x in innerResult))

        return innerResult + (distance,)

#... 

class ExtractorFactory:
    def __init__(self):
        self.extractors = {
            'position':IndexRangeExtractor(0, 3),
            'velocity':EuclideanDistanceExtractorDecorator(
                IndexRangeExtractor(3, 6)),
            'forces':EuclideanDistanceExtractorDecorator(
                IndexRangeExtractor(6, 9))}

    def createExtractor(self, quantity):
        return self.extractors[quantity]


alist = [1,2,3,4,5,6,7,8,9]
ef = ExtractorFactory()
e1 = ef.createExtractor('position')
e2 = ef.createExtractor('velocity')
e3 = ef.createExtractor('forces')

print e1.extract(alist)
print e2.extract(alist)
print e3.extract(alist)

关于python - 代码味道 - if/else 构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20497748/

相关文章:

python - 为什么不同实例的字段在 python 模块中会混合在一起?

python - 从 zip 复制文件并同时读取该文件

php - "Undefined method PDO::execute()"尽管使用了准备

javascript - 如何消除 Angular Controller 中的代码重复?

c++ - 将仅 1 行代码不同的两个函数分组

python - 从另一个类方法调用类方法或常规方法之间的区别

python - 在excel中检查匹配数据的函数一直返回false

java - 如何将输出语句转换为字符串类型?

java - 我们可以使用反射调用抽象类的私有(private)方法吗?

java - 有没有办法缩短由于对象属性相似而重复的代码?