Union 赋值中的不兼容类型
Incompatible types in assignment on Union
Mypy 向我打印以下消息:
x.py:74: error: Incompatible types in assignment (expression has type
"Union[str, Dict[str, str]]", variable has type "str")
是不是很奇怪? str
是 Union[str, Dict[str, str]]
的一部分
代码如下:
def get_multiple(fields: List[str], config_data) -> Dict[str, str]:
config_results = {k: v for k, v in config_data.items() if k in fields}
log_missing_fields(fields, config_results)
return config_results
def get_single(field: List[str], config_data) -> str:
result = config_data.get(field)
if result is None:
log.warning('The following fields are missing: %s', field)
return result
def get(fields: Union[str, List[str]]) -> Union[str, Dict[str, str]]:
log.debug('Retrieving values %s from config', str(fields))
config_data = read_config()
get_data = get_multiple if isinstance(fields, list) else get_single
return get_data(fields, config_data)
def get_ts_url() -> str:
timeout = get('timeout') # type: str <-- Line 74 is here
log.info('Trying to connect the servers.')
with db_session() as db_handler:
url = scan_availability(db_handler, int(timeout))
if url:
return url
log.critical("Could not find available servers.")
raise ConnectionError("Could not find available servers.")
避免此问题的正确方法是使用 @overload
装饰器来描述函数参数与其结果之间的关系。
函数 get()
将 return 一个 str
(实际上是一个 Optional[str]
因为它也可能 return None
)如果它是传递了一个 str
,如果传递了一个 list
,它将 return 一个字典。以下是我们如何使用类型注释来描述它:
from typing import *
def read_config() -> Dict[str, str]:
return {}
def get_multiple(fields: List[str], config_data: Dict[str, str]) -> Dict[str, str]:
config_results = {k: v for k, v in config_data.items() if k in fields}
return config_results
def get_single(field: List[str], config_data: Dict[str, str]) -> Optional[str]:
result = config_data.get(field)
return result
@overload
def get(fields: str) -> Optional[str]: ...
@overload
def get(fields: List[str]) -> Dict[str, str]: ...
def get(fields):
config_data = read_config()
get_data = get_multiple if isinstance(fields, list) else get_single
return get_data(fields, config_data)
def get_ts_url() -> None:
timeout = get('timeout')
if TYPE_CHECKING:
reveal_type(timeout)
如果你运行 mypy 在此它会打印
Revealed type is 'Union[builtins.str, builtins.None]'
以后我还建议在发布之前花几分钟时间来简化您的示例,以便其他人可以重现它。
Mypy 向我打印以下消息:
x.py:74: error: Incompatible types in assignment (expression has type "Union[str, Dict[str, str]]", variable has type "str")
是不是很奇怪? str
是 Union[str, Dict[str, str]]
代码如下:
def get_multiple(fields: List[str], config_data) -> Dict[str, str]:
config_results = {k: v for k, v in config_data.items() if k in fields}
log_missing_fields(fields, config_results)
return config_results
def get_single(field: List[str], config_data) -> str:
result = config_data.get(field)
if result is None:
log.warning('The following fields are missing: %s', field)
return result
def get(fields: Union[str, List[str]]) -> Union[str, Dict[str, str]]:
log.debug('Retrieving values %s from config', str(fields))
config_data = read_config()
get_data = get_multiple if isinstance(fields, list) else get_single
return get_data(fields, config_data)
def get_ts_url() -> str:
timeout = get('timeout') # type: str <-- Line 74 is here
log.info('Trying to connect the servers.')
with db_session() as db_handler:
url = scan_availability(db_handler, int(timeout))
if url:
return url
log.critical("Could not find available servers.")
raise ConnectionError("Could not find available servers.")
避免此问题的正确方法是使用 @overload
装饰器来描述函数参数与其结果之间的关系。
函数 get()
将 return 一个 str
(实际上是一个 Optional[str]
因为它也可能 return None
)如果它是传递了一个 str
,如果传递了一个 list
,它将 return 一个字典。以下是我们如何使用类型注释来描述它:
from typing import *
def read_config() -> Dict[str, str]:
return {}
def get_multiple(fields: List[str], config_data: Dict[str, str]) -> Dict[str, str]:
config_results = {k: v for k, v in config_data.items() if k in fields}
return config_results
def get_single(field: List[str], config_data: Dict[str, str]) -> Optional[str]:
result = config_data.get(field)
return result
@overload
def get(fields: str) -> Optional[str]: ...
@overload
def get(fields: List[str]) -> Dict[str, str]: ...
def get(fields):
config_data = read_config()
get_data = get_multiple if isinstance(fields, list) else get_single
return get_data(fields, config_data)
def get_ts_url() -> None:
timeout = get('timeout')
if TYPE_CHECKING:
reveal_type(timeout)
如果你运行 mypy 在此它会打印
Revealed type is 'Union[builtins.str, builtins.None]'
以后我还建议在发布之前花几分钟时间来简化您的示例,以便其他人可以重现它。