强制继承类型的兼容性(Python)

时间:2011-08-17 15:05:58

标签: python inheritance

假设有人为您提供了一对可以协同工作的现有课程:

class non_unique_collection:
    def __init__(self):
        self.all_items = []
    def add_new_item(self, item):
        self.all_items.append(item)
    def __len__(self):
        return len(self.all_items)
    ## ...
    ## there are several other useful functions here
    ## ...
    def overlap(self, n_u_tuple):
        # do some things here
        pass

class non_unique_ranked_collection:
    def __init__(self, some_scores_and_items):
        self.ranked_items = sorted(some_scores_and_items)

我想使用该类的许多功能(例如__len__),但我想改变一些非常基本的功能:

class unique_collection(non_unique_collection):
    def __init__(self):
        self.all_items = set([])
    def add_new_item(self, item):
        self.all_items.add(item)

我还希望将我的派生unique_collection课程用于另一个新课程unique_ranked_collection

class unique_ranked_collection(non_unique_ranked_collection):
    def __init__(self, some_scores_and_items):
        # average scores for duplicate items
        items_to_scores = {}
        for score, item in some_scores_and_items:
            if item in items_to_scores:
                items_to_scores[item].append(score)
            else:
                items_to_scores[item] = [ score ]
        average_scores_and_unique_items = dict( [ (sum(items_to_scores[item])/float(len(items_to_scores[item])), item) for item in items_to_scores ] )
        self.ranked_items = sorted(average_scores_and_unique_items)

这是我的问题:

最佳方式是什么,以便overlap函数可以与non_unique_collectionnon_unique_ranked_collection或{{1}一起使用和unique_collection(但unique_ranked_collectionunique...类型之间)?我开始使用non_unique...添加一些断言语句,但它看起来很混乱,我想征求意见。

我能想到的最好的事情是拥有两个isinstanceunique...类型继承的基类。你怎么看待这个?

非常感谢。

PS--我知道代码编写的这个特定问题非常无趣,但它只是一个例子。

2 个答案:

答案 0 :(得分:1)

如果你真的想强制执行此操作,请三思。不推荐对Python进行严格的类型检查,因为它可以防止“鸭子打字”。

此外,面向对象编程中的继承模拟是一个关系。由于unique_ranked_collection继承自non_unique_ranked_collection,因此前一类的实例是后一类的一种:

>>> obj = unique_ranked_collection()
>>> isinstance(obj, non_unique_ranked_collection)
True

因此,non_unique_collection.overlap() 应该接受unique_ranked_collection

如果您必须强制执行unique_collection.overlap()只接受unique_ranked_collection,只需覆盖该方法:

class unique_collection(non_unique_collection):

    # ...

    def overlap(self, other):
        if not isinstance(other, unique_ranked_collection):
            raise TypeError('expected an unique_ranked_collection')
        return super(unique_collection, self).overlap(other)

答案 1 :(得分:0)

您可以通过标记类,并在所有类中使用overlap外部函数而不是方法,明确提及要允许调用overlap的“类型”。

我认为这不是非常pythonic,因为它试图强制类上的类型,但它们是弱类型,将它们视为“重叠桶”,但它取决于您的实际用例。

另一个问题是,在您的示例中,unique_collection non_unique_collection(继承自它),同样unique_ranked_collection non_unique_ranked_collection,这意味着您需要一个复杂的类矩阵来对其进行排序,或使用类似下面的示例:

class non_unique_collection:
    type = 'N'

class non_unique_ranked_collection:
    type = 'N'

class unique_collection(non_unique_collection):
    type = 'U'

class unique_ranked_collection(non_unique_ranked_collection):
    type = 'U'

def overlap(collection1, collection2):
    if collection1.type != collection2.type:
        raise TypeError
    return True