2017-07-27 61 views
1

在分配不兼容的類型給出了以下類:mypy AnyStr給出簡單的例子

from typing import AnyStr 

class A(object): 

    def __init__(self, param): 
     # type: (AnyStr) -> None 
     self.a = param # type: AnyStr 

我得到以下輸出:

$ mypy . -v 
LOG: Mypy version 0.521 
LOG: Build finished in 1.199 seconds with 10 modules, 2076 types, and 2 errors 
test.py:8: error: Incompatible types in assignment (expression has type "str", variable has type "AnyStr") 
test.py:8: error: Incompatible types in assignment (expression has type "bytes", variable has type "AnyStr" 

如何走到這一步分配運算給出了不兼容的類型?

回答

1

我不是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 ,它的意圖是或者strbytes,但它必須是一致在給定的函數調用範圍內。它們給出一個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的範圍之外的可變變量(例如全局或類的屬性)沒有意義,這可能是失敗的原因。我懷疑這個錯誤信息可能會更清楚。

解決方案

取決於你真正想要實現的目標,這裏有幾個解決方案。如果你是strbytes之間真正的不可知論者,那麼你可以使用Union[Text, bytes]

打字進口聯盟,文本,AnyStr

class A: 
    def __init__(self, a): 
     #type: (AnyStr) -> None 
     self.param = a # type: Union[Text, bytes] 

注意,在這種情況下,我在輸入使用AnyStr,但在這種情況下,它相當於Union[Text, bytes],因爲只有一個參數。或者,如果你真的做一下參數是否是strbytes護理,你可以採取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。