??
),允许在赋值期间轻松(简短)进行null检查:string s = null;
var other = s ?? "some default value";
是否有python等效项?
我知道我可以做到:
s = None
other = s if s else "some default value"
但是还有没有更短的方法(我不需要重复
s
)?#1 楼
other = s or "some default value"
好,必须弄清楚
or
运算符的工作方式。它是一个布尔运算符,因此可以在布尔上下文中工作。如果这些值不是布尔值,则出于运算符的目的将它们转换为布尔值。请注意,
or
运算符不只返回True
或False
。相反,如果第一个操作数的结果为true,则返回第一个操作数;如果第一个操作数的结果为false,则返回第二个操作数。在这种情况下,表达式x or y
如果为x
,则返回True
。或转换为布尔值时的值为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"
如果使用变量
s
要保存对类实例或None
的引用(只要您的类未定义成员__nonzero__()
和__len__()
),则使用与null运算符相同的语义是安全的。实际上,具有Python的这种副作用甚至可能是有用的。由于您知道哪些值的计算结果为false,因此可以使用它来触发默认值,而不必专门使用
None
(例如,错误对象)。在某些语言中,此行为称为猫王运算符。
评论
这项工作会一样吗?我的意思是,如果s是一个有效值但不真实,它会中断吗? (我不了解Python,所以我不确定“真实”的概念是否适用。)
– cHao
2011-2-12 15:33
除常量False之外,数字0,无和空容器(包括字符串)也被视为false。大多数其他一切都被认为是真实的。我要说的是,这里的主要危险是您将获得一个真实但非字符串的值,但这在某些程序中不会成为问题。
– Kindall
2011年2月12日15:52
如果s为None或False,则使用此其他将获得默认值,这可能不是所需的值。
–pafcu
2011-2-12在16:15
也有许多由此引起的模糊错误。例如,在Python 3.5之前,datetime.time(0)也很虚假!
–安蒂·哈帕拉(Antti Haapala)
16年1月20日,0:06
这不好。我建议添加有关其陷阱的通知。并建议不要使用它。
–玛蒂·乌尔哈克(Mateen Ulhaq)
18年7月1日在4:57
#2 楼
严格地,other = s if s is not None else "default value"
否则,
s = False
将变成"default value"
,这可能不是预期的。如果要使其更短,试试:
def notNone(s,d):
if s is None:
return d
else:
return s
other = notNone(s, "default value")
评论
考虑x()?. y()?. z()
– Nurettin
20-4-24在11:08
#3 楼
这是一个函数,该函数将返回不是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()
可能不必要地遍历所有参数,即使第一个参数不是None
,因此您也可以使用以下版本:def coalesce(*arg):
for el in arg:
if el is not None:
return el
return None
评论
def coalesce(* arg):返回next((如果a不为None,则a为arg中的a),None)与上一行示例相同。
– glglgl
2014年6月24日12:44
我知道人们想解释sytnax等,但是结盟采用了任意参数列表,因此这实际上应该是最佳答案。
–埃里克·特威格(Eric Twilegar)
2014年7月3日在5:02
glglgl是最好的答案。我在大型测试阵列上使用了timeit,reduce的实现速度慢得令人无法接受,for / if版本的多行速度最快,而下一个实现则略微落后。考虑到简单性和简洁性,下一个版本是最佳的总体选择。
–粘土
2015年6月9日在20:57
@glglgl有有趣的摘要。不幸的是,由于Python没有名字传递,像这样的合并不会造成短路。在代码运行之前,将评估所有参数。
–user1338062
18-09-17在9:47
考虑x()?. y()?. z()
– Nurettin
20-4-24在11:07
#4 楼
我知道已经解决了,但是在处理对象时还有另一种选择。如果您的对象可能是:
{
name: {
first: "John",
last: "Doe"
}
}
您可以使用:
obj.get(property_name, value_if_null)
:
obj.get("name", {}).get("first", "Name is missing")
通过添加
{}
作为默认值,如果缺少“名称”,则返回一个空对象并将其传递给下一个对象得到。这类似于C#中的null安全导航,就像obj?.name?.first
。评论
并非所有对象都具有.get,这仅适用于类似dict的对象
–timdiels
19年2月22日在16:18
我正在提交答案编辑,以同时覆盖getattr()。
– dgw
19年8月20日在20:35
如果值是None,则get on dict不使用默认参数,但由于键不在dict中,因此值不存在时,则使用默认参数。 {'a':None} .get('a','我不想要None')仍然会给您None。
–帕特里克·梅夫克(Patrick Mevzek)
20年1月29日在22:33
#5 楼
如果您需要嵌套多个null合并操作,例如:model?.data()?.first()
用
or
可以轻松解决这个问题。 .get()
也不能解决此问题,因为getattr()
需要字典类型或类似类型(并且不能嵌套),或者q4312079q会在NoneType没有属性时抛出异常。 考虑向该语言添加空合并的相关点是PEP 505,与该文档相关的讨论在python-ideas线程中。
#6 楼
除了Juliano关于“或”的行为的答案:它是“快速”的
>>> 1 or 5/0
1
所以有时它对于诸如
之类的东西来说可能是有用的捷径/>
object = getCachedVersion() or getFromDB()
评论
您要查找的术语是“短路”。
– jpmc26
2014年11月7日,0:05
#7 楼
对于单个值,除了@Bothwells答案(我更喜欢)之外,为了对函数返回值进行空值检查,您可以使用新的walrus-operator(自python3.8起):def test():
return
a = 2 if (x:= test()) is None else x
因此,不需要对
test
函数进行两次评估(与a = 2 if test() is None else test()
一样)#8 楼
关于@Hugh Bothwell,@ mortehu和@glglgl的回答。设置用于测试的数据集
import random
dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]
定义实现
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)
进行测试功能
def test_func(dataset, func):
default = 1
for i in dataset:
func(i, default)
在Mac i7 @ 2.7Ghz上使用python 2.7的结果
>>> %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
很明显,
not_none
函数可以正确回答OP的问题并处理“虚假”问题。它也是最快,最容易阅读的。如果在许多地方都应用逻辑,显然这是最好的方法。如果您想在迭代中找到第一个非空值,那么@mortehu的响应是要走的路。但这是与OP不同的解决方案,尽管它可以部分解决这种情况。它不能采用可迭代的AND默认值。最后一个参数将是返回的默认值,但是在那种情况下,您将不会传递可迭代的值,而且也不清楚最后一个参数是否是value的默认值。
您可以在下面进行操作,但单值用例仍将使用
not_null
。def coalesce(*args, **kwargs):
default = kwargs.get('default')
return next((a for a in arg if a is not None), default)
#9 楼
对于像我这样偶然发现此问题的解决方案的人,当变量可能未定义时,我得到的最接近的变量是: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')
请注意,字符串在检查全局变量时需要使用此变量,但随后在检查值时将使用实际变量。
有关变量存在的更多信息:
如何检查变量是否存在?
评论
(变量名或False)== True与变量名== True相同
–mic
20 Apr 15'2:47
#10 楼
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 = ['Jack','Maria','Betsy','James','Jack']
names_repeated = dict()
default_value = 0
for find_name in names:
names_repeated[find_name] = names_repeated.get(find_name, default_value) + 1
如果您在字典中找不到名称,它将返回default_value,
如果该名称存在,则它将添加任何现有的带有1的值。
希望这会有所帮助
评论
嗨,欢迎来到Stack Overflow。您的答案添加了哪些新信息,而现有答案尚未涵盖这些信息?例如,请参见@Craig的答案
–格里西
19-10-18在0:31
#11 楼
我发现下面的两个函数在处理许多可变测试用例时非常有用。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
评论
这种事情增加了一大堆稍微不同的术语(例如,“ null”和“ nz”,在Python的上下文中都不表示任何东西),从其他语言中导入,并带有变体(严格或非严格!)。这只会增加混乱。显式“为无”检查是您应该使用的检查。另外,您不会从操作员使用函数调用时可以使用的任何快捷语义中受益。
– spookylukey
17年2月7日在10:35
评论
??运营商被提议为PEP505。..但从未将其翻译成语言。