私はPython 3.5をMypyと一緒に使用して、スクリプトの基本的な静的チェックを行っています。最近、OrderedDictを返すようにいくつかのメソッドをリファクタリングしましたが、「 'type'オブジェクトは下付きではありません」というエラーが発生しました。キーと値のタイプを指定してreturnアノテーションを使用しようとしたとき。
削減された例:
#!/usr/bin/env python3.5
from collections import OrderedDict
# this works
def foo() -> OrderedDict:
result = OrderedDict() # type: OrderedDict[str, int]
result['foo'] = 123
return result
# this doesn't
def foo2() -> OrderedDict[str, int]:
result = OrderedDict() # type: OrderedDict[str, int]
result['foo'] = 123
return result
print(foo())
そして、これはpython実行時の出力です:
Traceback (most recent call last):
File "./foo.py", line 12, in <module>
def foo2() -> OrderedDict[str, int]:
TypeError: 'type' object is not subscriptable
ただし、Mypyはコメントの型注釈に問題はなく、実際にresult[123] = 123
を実行しようとすると警告が表示されます。
何が原因ですか?
Mypyには問題はありません(少なくとも0.501では問題ありません)。しかし、そこにはis Python 3.6.0。に関する問題があります。以下を考慮してください。
from collections import OrderedDict
from typing import Dict
def foo() -> Dict[str, int]:
result: OrderedDict[str, int] = OrderedDict()
result['two'] = 2
return result
このコードは、mypy(0.501)とPython(3.6.0)の両方を満たします。ただし、Dict
をOrderedDict
に置き換えても、mypyは幸せですが、実行するとTypeError: 'type' object is not subscriptable
。
興味深いのは、Pythonインタープリターが関数のシグニチャーで下付きのOrderedDict
を見ると死にますが、変数タイプの注釈でそれを受け入れて喜んでいることです。
とにかく、これに対する私の回避策は、関数のシグネチャでDict
ではなくOrderedDict
を使用することです(Python通訳は正しい署名を受け入れることを学びます)。
回避策として、戻り値の型を文字列に入れて、MypyとPython 3.6の両方を満たすようにすることもできます。
from collections import OrderedDict
def foo() -> 'OrderedDict[str, int]':
result = OrderedDict()
result['foo'] = 123
return result
また、MutableMapping
を使用することもできます(この回答のように https://stackoverflow.com/a/44167921/138661 )
from collections import OrderedDict
from typing import Dict
def foo() -> MutableMapping[str, int]:
result = OrderedDict() # type: MutableMapping[str, int]
result['foo'] = 123
return result