python - 2 和 3 组合代码库中的 `__str__` 的类型是什么?
问题描述
我正在尝试转换这个 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__
是乙酸?(有没有更好的方法以 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 不会尝试分析该分支,因此不会报告错误。
如果您愿意,您可以更进一步,只需围绕 的整个定义执行 if-else __str__
:
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__
这是有关mypy 支持的版本和平台检查的更多信息。
mypy 没有具体理解该表单的事实sys.version_info.major
可能是一个疏忽。您可以尝试在mypy 的问题跟踪器consider_sys_version_info
上提交有关此问题的问题(尽管考虑到有简单的解决方法,我知道这个问题的优先级有多高),或者尝试通过修改.mypy/reachability.py
推荐阅读
- python - 如何使用 Python 将正则表达式应用于系列中的元素
- git - 如何通过 git 将颤振插件添加到另一个颤振项目?
- c# - Xamarin Forms Fusillade Refit - 使用单个 HttpClient 实例
- flutter - Flutter:如何使用字符串中的 mounth 更改日期时间格式?
- python - 每次我从 Python 库路径调用 .egg 时,AWS Glue 作业都会崩溃
- java - 在 Spring Boot 的同一个 pom.xml 中管理 H2 和 Postgres
- google-kubernetes-engine - 如何使运行在 GKE 上的 kubernetes pod 中的容器可以访问文件
- .net-core - IdentityServer4 重定向到带有客户端信息的登录操作
- python - 对 python 导入感到困惑(绝对和相对)
- c++ - 如何检索可变参数模板参数的类型?