2017-07-31 21 views
1

を定義するには、私はそうのようなqueue.Queueのサブクラスを持っている:mypy:どのように一般的なサブクラス

class SetQueue(queue.Queue): 
    """Queue which will allow a given object to be put once only. 

    Objects are considered identical if hash(object) are identical. 
    """ 

    def __init__(self, maxsize=0): 
     """Initialise queue with maximum number of items. 

     0 for infinite queue 
     """ 
     super().__init__(maxsize) 
     self.all_items = set() 

    def _put(self): 
     if item not in self.all_items: 
      super()._put(item) 
      self.all_items.add(item) 

私は静的型チェックのためにmypyを使用しようとしています。

from typing import Generic, Iterable, Set, TypeVar 

# Type for mypy generics 
T = TypeVar('T') 

class SetQueue(queue.Queue): 
    """Queue which will allow a given object to be put once only. 

    Objects are considered identical if hash(object) are identical. 
    """ 

    def __init__(self, maxsize: int=0) -> None: 
     """Initialise queue with maximum number of items. 

     0 for infinite queue 
     """ 
     super().__init__(maxsize) 
     self.all_items = set() # type: Set[T] 

    def _put(self, item: T) -> None: 
     if item not in self.all_items: 
      super()._put(item) 
      self.all_items.add(item) 

mypy「は、一般的なタイプの欠落型パラメータを」と言って、クラス定義行に警告がスローされます。この場合、SetQueueこれは、これまで私の試みである一般的なオブジェクトのT.を取る必要があります。

どこかでGeneric[T]が必要だと思っていますが、私が作ったすべての試みは構文エラーをスローします。ドキュメントのすべての例では、サブクラス化はGeneric[T]ですが、他のオブジェクトからサブクラス化することはありません。

SetQueueの汎用タイプを定義する方法を知っている人はいますか?

+1

'queue.QueueへのT' SetQueueを関連付けることができないので、私はその多重継承がうまくいきませんでした注意してください ''クラスSetQueue(queue.Queue、ジェネリック[T])との問題は何ですか? –

+0

質問を書いた後、私たちは複数の継承を使うべきかどうか疑問に思った。これは、既存のクラスをサブクラス化するクラス(型アノテーション自体を持たない)にジェネリック型を実装するための推奨された方法ですか? – blokeley

答えて

1

queue.Queueは実際にtyping.Genericから継承されていませんが、typeshed stubs for itと言われています。もしstdlibがtypingに完全に買収されるまで、これは少し必要な悪です。その結果、実際のqueue.Queueは、一般的なクラスにランタイムで彼ら__getitem__能力与えtyping.GenericMetaメタクラスはありません。たとえば

をmypyで[OK]をクリックし、このコードのタイプをチェックしますが、実行時に失敗します。

from typing import Generic, Iterable, Set, TypeVar, TYPE_CHECKING 
import queue 

# Type for mypy generics 
T = TypeVar('T') 


class SetQueue(queue.Queue[T]): 
    """Queue which will allow a given object to be put once only. 

    Objects are considered identical if hash(object) are identical. 
    """ 

    def __init__(self, maxsize: int=0) -> None: 
     """Initialise queue with maximum number of items. 

     0 for infinite queue 
     """ 
     super().__init__(maxsize) 
     self.all_items = set() # type: Set[T] 

    def _put(self, item: T) -> None: 
     if item not in self.all_items: 
      super()._put(item) 
      self.all_items.add(item) 


my_queue = queue.Queue() # type: queue.Queue[int] 
my_queue.put(1) 
my_queue.put('foo') # error 

my_set_queue = SetQueue() # type: SetQueue[int] 
my_set_queue.put(1) 
my_set_queue.put('foo') # error 

エラーが発生したのはTypeError: 'type' object is not subscriptableです。つまり、queue.Queue[T](つまりqueue.Queue.__getitem__)はサポートされていません。ここで

は、それは同様に、実行時に動作させるためにハックです:

from typing import Generic, Iterable, Set, TypeVar, TYPE_CHECKING 
import queue 

# Type for mypy generics 
T = TypeVar('T') 

if TYPE_CHECKING: 
    Queue = queue.Queue 
else: 
    class FakeGenericMeta(type): 
     def __getitem__(self, item): 
      return self 

    class Queue(queue.Queue, metaclass=FakeGenericMeta): 
     pass 


class SetQueue(Queue[T]): 
    """Queue which will allow a given object to be put once only. 

    Objects are considered identical if hash(object) are identical. 
    """ 

    def __init__(self, maxsize: int=0) -> None: 
     """Initialise queue with maximum number of items. 

     0 for infinite queue 
     """ 
     super().__init__(maxsize) 
     self.all_items = set() # type: Set[T] 

    def _put(self, item: T) -> None: 
     if item not in self.all_items: 
      super()._put(item) 
      self.all_items.add(item) 


my_queue = queue.Queue() # type: queue.Queue[int] 
my_queue.put(1) 
my_queue.put('foo') # error 

my_set_queue = SetQueue() # type: SetQueue[int] 
my_set_queue.put(1) 
my_set_queue.put('foo') # error 

メタクラスにパッチを適用するためのより良い方法があるかもしれません。私は誰かがより洗練されたソリューションを思い付くかどうかを知りたいのです。

編集:class SetQueue(queue.Queue, Generic[T])はS

関連する問題