strict_optional
标志。但是,请考虑一下:
emails = [get_user(uuid).email for uuid in user_uuids]
其中
get_user
理论上可以返回 None
,但在这个用例中,我知道它不能(如果确实如此,我也可以得到异常)。 这必须变成:
emails = []
for uuid in user_uuids:
user = get_user(uuid)
assert user is not None
emails.append(user.email)
在 TypeScript 中,有一个 非空断言运算符,它允许您仅添加
!
(如 getUser(uuid)!.email
中所示)。
有没有更好或更优雅的方法来处理这个问题?
我发现了两种接近非空断言运算符的方法,因此将类型
Optional[User]
转换为 User
:
typing.cast
from typing import cast
emails = [cast(User, get_user(uuid)).email for uuid in user_uuids]
对于 Python 3.12+:
def not_none[T](obj: T | None) -> T:
assert obj is not None
return obj
emails = [not_none(get_user(uuid)).email for uuid in user_uuids]
或更旧的 Python 版本:
from typing import Optional, TypeVar
T = TypeVar('T')
def not_none(obj: Optional[T]) -> T:
assert obj is not None
return obj
emails = [not_none(get_user(uuid)).email for uuid in user_uuids]
您没有理由不能在条件中使用相同的调用,所以
emails = [get_user(uuid).email for uuid in user_uuids if get_user(uuid)]
会起作用
@labroid 有一个很好的答案。一条评论提到调用 get_user 两次并不理想,因此我将在 labroid 的答案的基础上创建一个仅调用 get_user 一次的语句:
users = [
{"uuid":"abc", "email":"email"}
]
def get_user(uuid):
for user in users:
if user["uuid"] == uuid:
return user
return None
user_uuids = ["abc", "def"]
emails = [user["email"] for user in [get_user(uuid) for uuid in user_uuids] if user != None]
print(emails)
因为我不想调用 get_user 两次。 我会做这样的事情:
users = map(get_user, user_uuids)
emails = [user.email for user in users if user]
对我来说,这比我见过的任何东西都更具有Python风格。
Python 和其他一些语言具有短路功能,因此以下语句完全没问题
TestArr = [None, None, None, None]
ArrTest = [x.testFunc() for x in TestArr if x != None]
print(ArrTest)
并且将返回一个空白列表。
虽然我不熟悉
strict_optional
。