Python 中的安全解除引用
Groovy 有一个很好的安全取消引用运算符,这有助于避免 NullPointerExceptions:
variable?.method()
只有当 variable
不为 null
时,才会调用 method
。
有没有办法在Python中做同样的事情?或者我是否必须编写ifvariable:variable.method()
?
Groovy has a nice operator for safe dereferencing, which helps to avoid NullPointerExceptions:
variable?.method()
The method
will only be called, if variable
is not null
.
Is there a way to do the same in Python? Or do I have to write if variable: variable.method()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
编辑 2021:
有一个新的包,它是一种 hack,在 Python 中具有这种功能。这是存储库: https://github.com/paaksing/nullsafe-python
适用于 < code>AttributeError 和
KeyError
以及包装的对象类型将保持有效。
不,没有。
但是要检查
None
,您不要编写if x:
,而是编写if x is None:
。这是一个重要的区别 - 对于相当多可能完全有效的值(尤其是 0 等价数字和空集合),x
的计算结果为False
,而x is None
only 如果引用x
指向单例对象None
,则计算结果为True
。根据个人经验,很少需要这样的操作员。是的,
None
有时用于表示没有值。但不知何故 - 也许是因为惯用代码返回 空对象 ,其中明智或抛出异常以指示严重失败 - 我每月只会收到两次AttributeError: 'NoneType' object has no attribute '...'
两次。我认为这可能是一个错误。
null
有两个含义 - “忘记初始化”和“没有数据”。第一个是一个错误,应该抛出异常。第二种情况通常需要比“我们不调用这个方法”更复杂的处理。当我向数据库/ORM 请求UserProfile
时,它不存在,而我得到null
...我是否想默默地跳过该方法的其余部分?或者我真的想(当在“库代码”中时)抛出一个适当的异常(这样“用户(代码)”知道用户不在那里并且可以做出反应......或忽略它)或者(当我编写特定功能)向用户显示一条明智的消息(“该用户不存在,您无法将其添加到您的朋友列表中”)?EDIT 2021:
There is a new package that is sort of a hack featuring exactly this functionality in Python. Here is the repo: https://github.com/paaksing/nullsafe-python
Works with
AttributeError
andKeyError
aswellThe wrapped object typings will remain effective.
No, there isn't.
But to check for
None
, you don't writeif x:
, you writeif x is None:
. This is an important distinction -x
evaluates toFalse
for quite a few values that are propably perfectly valid (most notably 0-equivalent numbers and empty collections), whereasx is None
only evaluates toTrue
if the referencex
points to the singleton objectNone
.From personal experience, such an operator would be needed very rarely. Yes,
None
is sometimes used to indicate no value. But somehow - maybe because idiomatic code returns null objects where sensible or throws exceptions to indicate critical failure - I only get anAttributeError: 'NoneType' object has no attribute '...'
twice a month.I would argue that this might be a misfeature.
null
has two meanings - "forgot to initialize" and "no data". The first is an error and should throw an exception. The second case usually requires more elaborate handling than "let's just not call this method". When I ask the database/ORM for aUserProfile
, it's not there and I getnull
instead... do I want to silently skip the rest of the method? Or do I really want to (when in "library code") throw an approriate exception (so "the user (code)" knows the user isn't there and can react... or ignore it) or (when I'm coding a specific feature) show a sensible message ("That user doesn't exist, you can't add it to your friend list") to the user?首先,您的选项取决于您希望表达式在变量不可取消引用的情况下求值。我假设
None
是这些示例中的适当结果。Python 中某些情况下的常见习惯用法是使用条件表达式:
虽然这种需求可能并不普遍,但在某些情况下它会很有用,特别是当引用是嵌套的并且您想要这样的东西时,该习惯用法很快就会变得很麻烦。
请注意,支持用于安全引用的
?.
运算符是 PEP 505:无意识的操作员\| Python.org。目前的状态是“延期”。有关它的一些讨论位于:
First of all, your options depend on what you'd like the expression to evaluate to if the variable is not dereferencable. I'll assume
None
is the appropriate result in these examples.A common idiom for some circumstances in Python uses conditional expressions:
While this need may not be widespread, there are circumstances where it would be useful, especially when the references are nested and you would want something like this, where that idiom quickly gets cumbersome.
Note that support for a
?.
operator for safe deferencing is one of the main topics of PEP 505: None-aware operators \| Python.org. It's current status is "deferred".Some discussion of it is at:
我已经在 Groovy 中使用过这个功能,所以我不会重复其他海报的 blub 悖论。
在 Groovy 中,像这样的语句
在 Python 中执行此操作
这绝对是 Groovy 中的一个很酷的功能,并且有助于消除语法噪音。还有一些其他的语法糖,例如 Elvis 运算符或 *,但它们确实牺牲了易读性作为快速修复符号的代价(换句话说,它们不是 Pythonic)。
希望有帮助:-)
I've used this feature in Groovy, so I won't repeat the blub paradox of other posters.
In Groovy a statement like this
Does this in Python
It's definitely a cool feature in Groovy, and is helpful in removing syntactical noise. There are a few other bits of syntactical sugar, like the Elvis operator or *, but they do sacrifice legibility as the expense for quick fix symbols (in other words, they're no Pythonic).
Hope that helps :-)
假设您正在解析 xml,并且当前正在编写以下内容:
Python 3.8 引入了赋值表达式(海象运算符)现在可以非常优雅地编写:
Let's say you're parsing xml, and you're currently writing this:
Python 3.8 introduced an assignment expression (the walrus operator) and can now write this pretty elegantly:
我见过并使用过的一个习惯用法是用
callable(func) 和 func(a, b, c)
代替普通函数调用(不使用返回值)。但是,如果您尝试使用返回值,并且该函数不可调用,则此习惯用法将产生False
,这可能不是您想要的。在这种情况下,您可以使用三元运算符来提供默认值。例如,如果函数返回一个要迭代的列表,则可以使用空列表作为默认值func(a, b, c) if callable(func) else []
。An idiom I have seen and used is
callable(func) and func(a, b, c)
in place of a plain function call (where the return value is not used). If you are trying to use the return value, however, this idiom will yieldFalse
if the function is not callable, which may not be what you want. In this case you can use the ternary operator to supply a default value. For example, if the function would return a list that you would iterate over, you could use an empty list as a default value withfunc(a, b, c) if callable(func) else []
.回答你的问题:是的,你需要编写 if-esle 子句,但使用 pythonic 方式:
Answering your question: yeah, you need to write if-esle clause, but use the pythonic way:
这可能非常 hacky,但出于我的目的,这已经删除了一些代码:
通过将您的调用包装在 lambda 中来使用它:
This might be very hacky, but for my purposes this has cut out a bit of code:
Use it by wrapping your call in a lambda:
Python没有这样的东西。这是因为 Python 中没有
null
指针。嗯,有一个特殊的None
值,它经常用于表示“无值”的情况。但这只是一个约定。None
是一个像所有其他值/对象一样的值/对象。并且由于没有null
,因此没有运算符来处理它。Python has no such thing. This is because there is no
null
pointer in Python. Well, there is the specialNone
value, which is often used in situations, where it represents "no value". But that is just a convention.None
is a value/object like all others. And since there is nonull
, there is no operator to deal with it.