Python 中是否存在与 C# 空合并运算符等效的函数?
在 C# 中,有一个 空合并运算符(写为 ? ?
),允许在赋值期间进行简单(简短)的空检查:
string s = null;
var other = s ?? "some default value";
是否有Python等效项?
我知道我可以这样做:
s = None
other = s if s else "some default value"
但是有没有更短的方法(我不需要重复 s
)?
In C# there's a null-coalescing operator (written as ??
) that allows for easy (short) null checking during assignment:
string s = null;
var other = s ?? "some default value";
Is there a python equivalent?
I know that I can do:
s = None
other = s if s else "some default value"
But is there an even shorter way (where I don't need to repeat s
)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
我意识到这个问题已经得到解答,但是当您处理类似字典的对象时,还有另一种选择。
如果您有一个对象可能是:
您可以使用:
例如:
通过添加
{}
作为默认值,如果缺少“name”,则会返回一个空对象并传递到下一个 get 。这类似于 C# 中的 null-safe-navigation,类似于obj?.name?.first
。I realize this is answered, but there is another option when you're dealing with dict-like objects.
If you have an object that might be:
You can use:
Like:
By adding
{}
as the default value, if "name" is missing, an empty object is returned and passed through to the next get. This is similar to null-safe-navigation in C#, which would be likeobj?.name?.first
.除了@Bothwells答案(我更喜欢)对于单个值之外,为了对函数返回值进行空检查分配,您可以使用新的海象运算符(自python3.8起):
因此,
test
函数不需要计算两次(如a = 2 if test() is None else test()
)Addionally to @Bothwells answer (which I prefer) for single values, in order to null-checking assingment of function return values, you can use new walrus-operator (since python3.8):
Thus,
test
function does not need to be evaluated two times (as ina = 2 if test() is None else test()
)除了 Juliano 关于“或”行为的回答之外:
它“快”
所以有时它可能是一个有用的快捷方式,例如
In addition to Juliano's answer about behavior of "or":
it's "fast"
So sometimes it's might be a useful shortcut for things like
处理可能的异常:
像这样使用它:
to take care of possible exceptions:
use it like that:
对于 2024 年仍需要函数空合并的任何人:
对我有用。如果您想要访问可能存在或不存在的字段,则此变体适用。例如,对于 foo.bar._name_,您将执行
null_coalesce(foo, 'bar', '__name__')
并且会收到函数的名称,或者如果字段不存在,您将得到 None 和 NOT an AttributeError。For anyone still in need of a null coalescing for functions in 2024:
worked for me. This variant works if you want to access a field that may or may not exist. E.g. for foo.bar._name_ you would execute
null_coalesce(foo, 'bar', '__name__')
and would either receive the name of the function or if this field does not exist, you would get None and NOT an AttributeError.关于 @Hugh Bothwell、@mortehu 和 @glglgl 的回答。
设置用于测试的数据
集定义
制作测试函数
实现使用python 2.7在mac i7 @2.7Ghz上
结果显然,
not_none
函数正确回答了OP的问题并处理了“虚假”问题。它也是最快且最容易阅读的。如果在很多地方应用这个逻辑,这显然是最好的方法。如果您遇到问题,想要在可迭代中查找第一个非空值,那么 @mortehu 的响应就是正确的选择。但它是一个与 OP 不同的问题的解决方案,尽管它可以部分处理这种情况。它不能采用可迭代值和默认值。最后一个参数将是返回的默认值,但是在这种情况下您不会传入可迭代对象,并且最后一个参数是默认值并不明确。
然后,您可以执行以下操作,但我仍将
not_null
用于单值用例。Regarding answers by @Hugh Bothwell, @mortehu and @glglgl.
Setup Dataset for testing
Define implementations
Make test function
Results on mac i7 @2.7Ghz using python 2.7
Clearly the
not_none
function answers the OP's question correctly and handles the "falsy" problem. It is also the fastest and easiest to read. If applying the logic in many places, it is clearly the best way to go.If you have a problem where you want to find the 1st non-null value in a iterable, then @mortehu's response is the way to go. But it is a solution to a different problem than OP, although it can partially handle that case. It cannot take an iterable AND a default value. The last argument would be the default value returned, but then you wouldn't be passing in an iterable in that case as well as it isn't explicit that the last argument is a default to value.
You could then do below, but I'd still use
not_null
for the single value use case.尝试一下
opytional
库。该库还提供了
or_else
和apply_if
来安全、富有表现力地处理可能为 None 的值。可通过 pip、python3 -m pip install opytional
进行安装。免责声明:我是图书馆作者
Give the
opytional
library a try.The library also provides
or_else
andapply_if
for safe, expressive handling of values that may be None. Installation is available via pip,python3 -m pip install opytional
.Disclaimer: am library author
我们可以这样尝试
We can try like this
我遇到了类似的问题,但上面的解决方案都不能让我满意。我做了一些测试,然后我想到了一个好主意......而且它有效!
我认为根据 Python 标准,它既优雅又具有足够的“描述性”。我会让你来判断。
首先是问题:
我有一个类
Completion
,它引用了sequence_type1
或sequence_type2
我想定义一个如下属性
:看起来不太好看,占用大量空间......而且我需要对
Completion
的所有属性执行相同的操作!我不能简单地这样做
,因为如果
self.sequence_type1
不存在,则会引发异常,而不是给我self.sequence_type2.seq_pk
但我发现效果很好的是以下:
我认为简单、描述性、优雅
I had a similar issue, but none of the solution above were quite satisfactory for me. I did some tests, then a nice idea came to my mind ... and it works !
it is at the same time elegant and 'descriptive' enough according to Python standards I think. I'll let you the judge of it.
First the issue:
I have a class
Completion
which has either a reference tosequence_type1
orsequence_type2
I want to define a property such as this:
That's not really nice looking, takes a lot of space ... and I will need to do the same for all the properties of
Completion
!I cannot simply do
because if
self.sequence_type1
does not exist, an exception will be raised, instead of giving meself.sequence_type2.seq_pk
But what I discovered works nicely is the following:
simple, descriptive, elegant I think
我没有解释
or
运算符的作用,以及它为什么不是一个有用的空合并运算符,而是提出了一个实用的coalesce
函数。验证它是否有效:
为了提高性能,当计算值的成本昂贵时,可以提供 lambda 函数而不是常量,这样,如果早期参数在运行时不是
None
,就可以避免这种费用。Rather than explain what the
or
operator does, and how it is not a useful null-coalescing operator, I propose a pragmaticcoalesce
function.Verify it works:
To improve performance one would supply a lambda function instead of a constant when the value is expensive to compute, and that way the expense can be avoided if an earlier argument is not
None
at runtime.如果在字典中找不到该名称,它将返回default_value,
如果该名称存在,那么它将添加任何现有值 1。
希望这可以有所帮助
if you cannot find the name inside the dictionary, it will return the default_value,
if the name exist then it will add any existing value with 1.
hope this can help
对于像我这样在这里偶然寻找解决此问题的可行解决方案的人,当变量可能未定义时,我得到的最接近的是:
请注意,在检查全局变量时需要一个字符串,但随后在检查时使用实际变量价值。
有关变量存在的更多信息:
如何检查变量是否存在?
For those like me that stumbled here looking for a viable solution to this issue, when the variable might be undefined, the closest i got is:
Note that a string is needed when checking in globals, but afterwards the actual variable is used when checking for value.
More on variable existence:
How do I check if a variable exists?
我发现下面的两个函数在处理许多变量测试用例时非常有用。
The two functions below I have found to be very useful when dealing with many variable testing cases.
好吧,必须弄清楚
or
运算符是如何工作的。它是一个布尔运算符,因此它在布尔上下文中工作。如果值不是布尔值,则出于运算符的目的,它们将转换为布尔值。请注意,
or
运算符不仅仅返回True
或False
。相反,如果第一个操作数的计算结果为 true,则返回第一个操作数;如果第一个操作数的计算结果为 false,则返回第二个操作数。在这种情况下,如果表达式
x 或 y
为True
,则返回x
,或者在转换为布尔值时计算结果为 true。否则,它返回y
。在大多数情况下,这与 C♯ 的空合并运算符的目的完全相同,但请记住:如果您使用变量
s
来保存对类的实例或None
(只要您的类未定义成员__nonzero__()
和__len__()
),就可以安全地使用与空合并运算符相同的语义。事实上,Python 的这种副作用甚至可能很有用。由于您知道哪些值的计算结果为 false,因此您可以使用它来触发默认值,而无需专门使用
None
(例如错误对象)。在某些语言中,此行为称为 Elvis 运算符。
Ok, it must be clarified how the
or
operator works. It is a boolean operator, so it works in a boolean context. If the values are not boolean, they are converted to boolean for the purposes of the operator.Note that the
or
operator does not return onlyTrue
orFalse
. Instead, it returns the first operand if the first operand evaluates to true, and it returns the second operand if the first operand evaluates to false.In this case, the expression
x or y
returnsx
if it isTrue
or evaluates to true when converted to boolean. Otherwise, it returnsy
. For most cases, this will serve for the very same purpose of C♯'s null-coalescing operator, but keep in mind:If you use your variable
s
to hold something that is either a reference to the instance of a class orNone
(as long as your class does not define members__nonzero__()
and__len__()
), it is secure to use the same semantics as the null-coalescing operator.In fact, it may even be useful to have this side-effect of Python. Since you know what values evaluates to false, you can use this to trigger the default value without using
None
specifically (an error object, for example).In some languages this behavior is referred to as the Elvis operator.
严格来说,
否则,
s = False
将变为“默认值”
,这可能不是预期的结果。如果您想让它更短,请尝试:
但请注意,由于这是一个函数,因此如果第一个值不是
None
,它不会像条件运算符那样短路;相反,即使第二个参数最终没有被使用,它也会评估两个参数。例如,如果a
不是None
,则notNone(a, get_some_value())
仍会调用get_some_value
,但是a if a is not None else get_some_value()
不会(运算符可以短路,条件运算符也可以)。Strictly,
Otherwise,
s = False
will become"default value"
, which may not be what was intended.If you want to make this shorter, try:
Note, though, that since that's a function, it won't short-circuit like the conditional operator would if the first value isn't
None
; instead, it will evaluate both arguments even through the second one doesn't end up being used. For example, ifa
is notNone
,notNone(a, get_some_value())
will still callget_some_value
, buta if a is not None else get_some_value()
won't (operators can short-circuit, and the conditional operator does).下面的函数将返回第一个不是
None
的参数:即使第一个参数不是
None,
,所以你也可以使用这个版本:reduce()
也可能不必要地迭代所有参数Here's a function that will return the first argument that isn't
None
:reduce()
might needlessly iterate over all the arguments even if the first argument is notNone
, so you can also use this version:如果您需要链接多个空条件操作,例如:
model?.data()?.first()
这不是一个使用
or
可以轻松解决的问题。它也不能用.get()
来解决,它需要字典类型或类似的类型(并且无论如何都不能嵌套)或getattr()
,当 NoneType 不存在时,它会抛出异常没有这个属性。考虑向语言中添加 null 感知运算符的相关 PEP 是 PEP 505 与该文档相关的讨论位于 python-ideas 线程。
In case you need to chain more than one null-conditional operation such as:
model?.data()?.first()
This is not a problem easily solved with
or
. It also cannot be solved with.get()
which requires a dictionary type or similar (and cannot be nested anyway) orgetattr()
which will throw an exception when NoneType doesn't have the attribute.The relevant PEP considering adding null-aware operators to the language is PEP 505 and the discussion relevant to the document is in the python-ideas thread.