我不是mypy的專家,但帶着一些偵探工作,我想我已經明白了這一點。
的問題
這似乎如果AnyStr
傳遞給函數工作得很好,但是當一個變量的類型是AnyStr
失敗。例如,這似乎很好地工作:
from typing import AnyStr
def f(a):
# type: (AnyStr) -> AnyStr
return a
if __name__ == "__main__":
print(f('cat'))
print(f(b'dog'))
但這種失敗:
from typing import AnyStr
c = 3 # type: AnyStr
與錯誤:
mypy_anystr.py:3: error: Invalid type "typing.AnyStr"
這是有道理的AnyStr
因爲這個想法,從the documentation ,它的意圖是或者str
或bytes
,但它必須是一致在給定的函數調用範圍內。它們給出一個AnyStr
用法的例子是:
def concat(a, b):
#type: (AnyStr, AnyStr) -> AnyStr
return a + b
concat('one', 'two') # OK
concat(b'three', b'four') # OK
concat('five', b'six') # Error
當然,除非AnyStr
是全局的(和上面的例子表明,它是不),則分配所述原始AnyStr
的範圍之外的可變變量(例如全局或類的屬性)沒有意義,這可能是失敗的原因。我懷疑這個錯誤信息可能會更清楚。
解決方案
取決於你真正想要實現的目標,這裏有幾個解決方案。如果你是str
和bytes
之間真正的不可知論者,那麼你可以使用Union[Text, bytes]
:
打字進口聯盟,文本,AnyStr
class A:
def __init__(self, a):
#type: (AnyStr) -> None
self.param = a # type: Union[Text, bytes]
注意,在這種情況下,我在輸入使用AnyStr
,但在這種情況下,它相當於Union[Text, bytes]
,因爲只有一個參數。或者,如果你真的做一下參數是否是str
或bytes
護理,你可以採取AnyStr
並將其轉換爲版本,你要主動:
from typing import Union, Text, AnyStr
from six import binary_type
class A:
def __init__(self, a):
#type: (AnyStr) -> None
if isinstance(a, binary_type):
b = a.decode() # type: Text
else:
b = a
self.param = b # type: Text
注意,這可以得到質樸如果a
是編碼在一個奇怪的語言環境或東西,所以要注意,這是一個簡化的例子,如果您嘗試主動解碼對象的YMMV。