处理Python中缺少非空断言运算符的问题

问题描述 投票:0回答:5

我想允许 Mypy'

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
中所示)。

有没有更好或更优雅的方法来处理这个问题?

python mypy python-typing
5个回答
15
投票

我发现了两种接近非空断言运算符的方法,因此将类型

Optional[User]
转换为
User
:

1) 使用
typing.cast

from typing import cast

emails = [cast(User, get_user(uuid)).email for uuid in user_uuids]

2)用函数模仿非空断言

对于 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]

1
投票

您没有理由不能在条件中使用相同的调用,所以

emails = [get_user(uuid).email for uuid in user_uuids if get_user(uuid)]

会起作用


1
投票

@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)

1
投票

因为我不想调用 get_user 两次。 我会做这样的事情:

users = map(get_user, user_uuids)
emails = [user.email for user in users if user]

对我来说,这比我见过的任何东西都更具有Python风格。


0
投票

Python 和其他一些语言具有短路功能,因此以下语句完全没问题

TestArr = [None, None, None, None]
ArrTest = [x.testFunc() for x in TestArr if x != None]
print(ArrTest)

并且将返回一个空白列表。

虽然我不熟悉

strict_optional

© www.soinside.com 2019 - 2024. All rights reserved.