按形状缩小联合
Narrow Union by shape
如何按形状缩小Union
?我不想使用 isinstance
或手动转换(有很多类型)来检查实际类型。我也不能修改类型定义。
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # error
else:
print(r.name) # error
类型检查错误说:
(variable) title: str | Unknown
Cannot access member "title" for type "Y"
Member "title" is unknown
Cannot access member "title" for type "Z"
Member "title" is unknown
(variable) name: Unknown | str
Cannot access member "name" for type "X"
Member "name" is unknown
问题
在某种程度上,Pylance 检查器是正确的。
类型不相关。不会有相关类型的检查错误:
class Base:
title: str
name: str
class X(Base):
title = "1"
class Y(Base):
name = "2"
class Z(Base):
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # no error
else:
print(r.name) # no error
此外,duck typing不适用,因为成员集不同。如果类型被认为是等价的,就不会出现错误:
class X:
name: str
title = "1"
class Y:
name = "2"
title: str
class Z:
name = "3"
title: str
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # no error
else:
print(r.name) # no error
解决方法
虽然您可以欺骗 Pylance 检查器,使其不会抱怨代码,但有几个选项:
选项 1。Suppress 类型检查
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # type: ignore
else:
print(r.name) # type: ignore
选项 2. 使用动态访问 getattr
而不是直接成员访问
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(getattr(r, "title"))
else:
print(getattr(r, "name"))
如何按形状缩小Union
?我不想使用 isinstance
或手动转换(有很多类型)来检查实际类型。我也不能修改类型定义。
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # error
else:
print(r.name) # error
类型检查错误说:
(variable) title: str | Unknown
Cannot access member "title" for type "Y"
Member "title" is unknown
Cannot access member "title" for type "Z"
Member "title" is unknown
(variable) name: Unknown | str
Cannot access member "name" for type "X"
Member "name" is unknown
问题
在某种程度上,Pylance 检查器是正确的。
类型不相关。不会有相关类型的检查错误:
class Base:
title: str
name: str
class X(Base):
title = "1"
class Y(Base):
name = "2"
class Z(Base):
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # no error
else:
print(r.name) # no error
此外,duck typing不适用,因为成员集不同。如果类型被认为是等价的,就不会出现错误:
class X:
name: str
title = "1"
class Y:
name = "2"
title: str
class Z:
name = "3"
title: str
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # no error
else:
print(r.name) # no error
解决方法
虽然您可以欺骗 Pylance 检查器,使其不会抱怨代码,但有几个选项:
选项 1。Suppress 类型检查
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(r.title) # type: ignore
else:
print(r.name) # type: ignore
选项 2. 使用动态访问 getattr
而不是直接成员访问
class X:
title = "1"
class Y:
name = "2"
class Z:
name = "3"
for (i, r) in enumerate([X(), Y(), Z()]): # type of r: X | Y | Z
if hasattr(r, "title"):
print(getattr(r, "title"))
else:
print(getattr(r, "name"))