1

我想将集合的元素限制为某个类的实例。我应该设置子类并覆盖 add 方法吗?我该怎么做?

4

1 回答 1

2

首先,在构建一组自定义对象时,您可能需要查看这个问题及其答案。简而言之,您需要定义诸如__hash__()和之类的方法,__eq__()以便您可以将它们添加到集合中:

class Foo:
    def __init__(self, value=0):
        self.value = value
    def __hash__(self):
        return self.value
    def __eq__(self, other):
        return isinstance(other, Foo) and self.value == other.value

现在您可以比较对象和set罐子:

In [19]: a = Foo()

In [20]: b = Foo()

In [21]: c = Foo(1)

In [22]: a == b
Out[22]: True

In [23]: b == c
Out[23]: False

In [24]: s = set([a, b, c])

In [25]: s
Out[25]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>])

In [26]: s.add(Foo())

In [27]: s
Out[27]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>])

问题是,你仍然可以添加一些完全不同的东西:

In [28]: s.add(1)

In [29]: s
Out[29]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>,
     1])

一种方法是按照您的建议覆盖add()方法:set

In [30]: class FooSet(set):
   ....:     def add(self, elem):
   ....:         if isinstance(elem, Foo):
   ....:             set.add(self, elem)
   ....:         else:
   ....:             raise TypeError('%s is not a Foo' % elem)
   ....:             # or just put "pass" here for silent behavior

In [31]: s = FooSet([a, b, c])

In [32]: s
Out[32]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>])

In [33]: s.add(Foo())

In [34]: s
Out[34]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>])

In [35]: s.add(Foo(2))

In [36]: s
Out[36]: 
set([<__main__.Foo instance at 0x267f758>,
     <__main__.Foo instance at 0x267f950>,
     <__main__.Foo instance at 0x26808c0>])

In [37]: s.add(2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

...

TypeError: 2 is not a Foo
于 2012-04-25T12:19:39.947 回答