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])

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 に答える