我正在尝试转换这个 py2 类:
class Example(object):
def __unicode__(self):
return unicode(42) # unicode(self.id)
def __str__(self):
return unicode(self).encode('u8')
__repr__ = __str__
到组合的 2/3 版本,类型为:
import sys
from typing import Text
from builtins import str as text
class Example(object):
def _as_unicode(self): # type: () -> Text
return text(42)
__unicode__ = _as_unicode
def _as_bytes(self): # type: () -> bytes
return self._as_unicode().encode('utf-8')
def __str__(self): # type: () -> str
if sys.version_info.major == 2:
return self._as_bytes() # line 17
else:
return self._as_unicode() # line 19
__repr__ = __str__
这会产生以下错误:
c:\tmp> py -3 -m mypy example.py
example.py:17: error: Incompatible return value type (got "bytes", expected "str")
c:\tmp> py -3 -m mypy example.py -2
example.py:19: error: Incompatible return value type (got "unicode", expected "str")
有没有办法让mypy相信__str__
的类型是copacet?
(有没有更好的方法以 2 + 3 兼容的方式编写此代码?)
最佳答案
这里正确的方法实际上不是尝试找到某种可以桥接两个 Python 版本的类型,而是让 mypy 了解您的分支仅在某些版本的 Python 上运行。
为此,请将 sys.version_info.major == 2
更改为如下所示的检查 sys.version_info[0] == 2
,例如:
import sys
from typing import Text
from builtins import str as text
class Example(object):
def _as_unicode(self): # type: () -> Text
return text(42)
def _as_bytes(self): # type: () -> bytes
return self._as_unicode().encode('utf-8')
def __str__(self): # type: () -> str
if sys.version_info[0] == 2:
return self._as_bytes()
else:
return self._as_unicode()
__unicode__ = _as_unicode
__repr__ = __str__
这最终完全回避了你的问题。例如。由于在 Python 2.7 模式下进行类型检查时“else”分支被标记为无法访问,因此 mypy 不会尝试分析该分支,因此不会报告错误。
如果您愿意,您可以更进一步,只需围绕 __str__
的整个定义执行一个 if-else:
import sys
from typing import Text
from builtins import str as text
class Example(object):
def _as_unicode(self): # type: () -> Text
return text(42)
def _as_bytes(self): # type: () -> bytes
return self._as_unicode().encode('utf-8')
if sys.version_info[0] == 2:
__str__ = _as_bytes
else:
__str__ = _as_unicode
__unicode__ = _as_unicode
__repr__ = __str__
这里有一些 more info on the version and platform checks mypy 支持。
事实上 mypy 不具体理解 sys.version_info.major
的形式可能是一个疏忽。您可以尝试在 mypy's issue tracker 上提交有关此问题的问题(尽管我不知道这个优先级有多高,因为有简单的解决方法),或者尝试通过修改 consider_sys_version_info
函数 in mypy/reachability.py
来自行添加对此的支持。 .
关于python - 2 和 3 组合代码库中 `__str__` 的类型是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57483303/