Я не разбираюсь в своих проблемах, но, немного поработав детективом, я думаю, что понял это.
Эта проблема
Кажется, это работает нормально, если 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
взята из документации, заключается в том, что она предназначена быть либо 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]
:
от ввода import Union, Text, 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, если вы пытаетесь активно декодировать объекты bytes
.
person
Paul
schedule
27.07.2017