是否有等效于 C# 空合并运算符的 Python?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4978738/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a Python equivalent of the C# null-coalescing operator?
提问by Klaus Byskov Pedersen
In C# there's a null-coalescing operator(written as ??) that allows for easy (short) null checking during assignment:
在 C# 中有一个空合并运算符(写为??),它允许在赋值期间进行简单(短)空检查:
string s = null;
var other = s ?? "some default value";
Is there a python equivalent?
有 python 等价物吗?
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)?
但是有没有更短的方法(我不需要重复s)?
采纳答案by Juliano
other = s or "some default value"
Ok, it must be clarified how the oroperator 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.
好的,必须弄清楚or操作员是如何工作的。它是一个布尔运算符,所以它在布尔上下文中工作。如果值不是布尔值,则出于运算符的目的将它们转换为布尔值。
Note that the oroperator does not return only Trueor False. 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.
请注意,or运算符不只返回Trueor False。相反,如果第一个操作数的计算结果为真,它返回第一个操作数,如果第一个操作数的计算结果为假,它返回第二个操作数。
In this case, the expression x or yreturns xif it is Trueor evaluates to true when converted to boolean. Otherwise, it returns y. For most cases, this will serve for the very same purpose of C?'s null-coalescing operator, but keep in mind:
在这种情况下,表达式x or y返回x,如果它是True或评估为真时转换成布尔值。否则,它返回y。在大多数情况下,这将用于与 C? 的空合并运算符完全相同的目的,但请记住:
42 or "something" # returns 42
0 or "something" # returns "something"
None or "something" # returns "something"
False or "something" # returns "something"
"" or "something" # returns "something"
If you use your variable sto hold something that is either a reference to the instance of a class or None(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.
如果您使用变量s来保存类实例的引用或None(只要您的类未定义成员__nonzero__()and __len__()),则使用与空合并运算符相同的语义是安全的。
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 Nonespecifically (an error object, for example).
事实上,Python 的这种副作用甚至可能很有用。由于您知道哪些值的计算结果为 false,因此您可以使用它来触发默认值,而无需None专门使用(例如,错误对象)。
In some languages this behavior is referred to as the Elvis operator.
在某些语言中,这种行为被称为Elvis 运算符。
回答by Hugh Bothwell
Strictly,
严格来说,
other = s if s is not None else "default value"
Otherwise, s = Falsewill become "default value", which may not be what was intended.
否则,s = False将变为"default value",这可能不是预期的。
If you want to make this shorter, try:
如果你想让它更短,请尝试:
def notNone(s,d):
if s is None:
return d
else:
return s
other = notNone(s, "default value")
回答by mortehu
Here's a function that will return the first argument that isn't None:
这是一个函数,它将返回第一个不是的参数None:
def coalesce(*arg):
return reduce(lambda x, y: x if x is not None else y, arg)
# Prints "banana"
print coalesce(None, "banana", "phone", None)
reduce()might needlessly iterate over all the arguments even if the first argument is not None, so you can also use this version:
reduce()即使第一个参数不是None,也可能不必要地迭代所有参数,因此您也可以使用此版本:
def coalesce(*arg):
for el in arg:
if el is not None:
return el
return None
回答by Orca
In addition to Juliano's answer about behavior of "or": it's "fast"
除了朱利亚诺关于“或”行为的回答:它是“快”
>>> 1 or 5/0
1
So sometimes it's might be a useful shortcut for things like
所以有时它可能是一个有用的捷径,比如
object = getCachedVersion() or getFromDB()
回答by Mike Stabile
The two functions below I have found to be very useful when dealing with many variable testing cases.
我发现下面的两个函数在处理许多可变测试用例时非常有用。
def nz(value, none_value, strict=True):
''' This function is named after an old VBA function. It returns a default
value if the passed in value is None. If strict is False it will
treat an empty string as None as well.
example:
x = None
nz(x,"hello")
--> "hello"
nz(x,"")
--> ""
y = ""
nz(y,"hello")
--> ""
nz(y,"hello", False)
--> "hello" '''
if value is None and strict:
return_val = none_value
elif strict and value is not None:
return_val = value
elif not strict and not is_not_null(value):
return_val = none_value
else:
return_val = value
return return_val
def is_not_null(value):
''' test for None and empty string '''
return value is not None and len(str(value)) > 0
回答by Craig
I realize this is answered, but there is another option when you're dealing with objects.
我意识到这已经得到了回答,但是在处理对象时还有另一种选择。
If you have an object that might be:
如果您的对象可能是:
{
name: {
first: "John",
last: "Doe"
}
}
You can use:
您可以使用:
obj.get(property_name, value_if_null)
Like:
喜欢:
obj.get("name", {}).get("first", "Name is missing")
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 like obj?.name?.first.
通过添加{}作为默认值,如果缺少“name”,则返回一个空对象并传递给下一个 get。这类似于 C# 中的空安全导航,类似于obj?.name?.first.
回答by debo
Regarding answers by @Hugh Bothwell, @mortehu and @glglgl.
关于@Hugh Bothwell、@mortehu 和@glglgl 的回答。
Setup Dataset for testing
设置数据集进行测试
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
Define implementations
定义实现
def not_none(x, y=None):
if x is None:
return y
return x
def coalesce1(*arg):
return reduce(lambda x, y: x if x is not None else y, arg)
def coalesce2(*args):
return next((i for i in args if i is not None), None)
Make test function
制作测试功能
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
Results on mac i7 @2.7Ghz using python 2.7
使用 python 2.7 在 mac i7 @2.7Ghz 上的结果
>>> %timeit test_func(dataset, not_none)
1000 loops, best of 3: 224 μs per loop
>>> %timeit test_func(dataset, coalesce1)
1000 loops, best of 3: 471 μs per loop
>>> %timeit test_func(dataset, coalesce2)
1000 loops, best of 3: 782 μs per loop
Clearly the not_nonefunction 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.
显然,该not_none函数正确回答了 OP 的问题并处理了“虚假”问题。它也是最快和最容易阅读的。如果在很多地方应用这个逻辑,这显然是最好的方法。
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 problemthan 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.
如果您想在可迭代对象中找到第一个非空值时遇到问题,那么@mortehu 的响应就是您要走的路。但它是一个与 OP不同的问题的解决方案,尽管它可以部分处理这种情况。它不能采用可迭代和默认值。最后一个参数将是返回的默认值,但是在这种情况下您不会传入可迭代对象,并且最后一个参数是默认值也不是明确的。
You could then do below, but I'd still use not_nullfor the single value use case.
然后你可以在下面做,但我仍然会使用not_null单值用例。
def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
回答by Angelo
Python has a get function that its very useful to return a value of an existent key, if the key exist;
if not it will return a default value.
def main():
names = ['Hyman','Maria','Betsy','James','Hyman']
names_repeated = dict()
default_value = 0
for find_name in names:
names_repeated[find_name] = names_repeated.get(find_name, 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.
如果在字典中找不到名称,它将返回 default_value,如果名称存在,则将任何现有值添加为 1。
hope this can help
希望这可以帮助
回答by Itaca
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:
对于像我这样偶然在这里寻找解决此问题的可行解决方案的人,当变量可能未定义时,我得到的最接近的是:
if 'variablename' in globals() and ((variablename or False) == True):
print('variable exists and it\'s true')
else:
print('variable doesn\'t exist, or it\'s false')
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?
关于变量存在的更多信息: 如何检查变量是否存在?
回答by Henhuy
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):
除了@Bothwells 对单个值的回答(我更喜欢)之外,为了对函数返回值进行空检查,您可以使用新的 walrus-operator(自 python3.8 起):
def test():
return
a = 2 if (x:= test()) is None else x
Thus, testfunction does not need to be evaluated two times (as in a = 2 if test() is None else test())
因此,test函数不需要被评估两次(如a = 2 if test() is None else test())

