Python 中的安全解除引用

发布于 2024-09-29 20:22:03 字数 267 浏览 5 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

机场等船 2024-10-06 20:22:03

编辑 2021:

有一个新的包,它是一种 hack,在 Python 中具有这种功能。这是存储库: https://github.com/paaksing/nullsafe-python

from nullsafe import undefined, _

value = _(variable).method()
assert value is undefined
assert not value
assert value == None

适用于 < code>AttributeError 和 KeyError 以及

dic = {}
assert _(dic)["nah"] is undefined
assert _(dic).nah is undefined

包装的对象类型将保持有效。


  1. 不,没有。

  2. 但是要检查None,您不要编写if x:,而是编写if x is None:。这是一个重要的区别 - 对于相当多可能完全有效的值(尤其是 0 等价数字和空集合),x 的计算结果为 False,而 x is None only 如果引用 x 指向单例对象 None,则计算结果为 True

  3. 根据个人经验,很少需要这样的操作员。是的,None 有时用于表示没有值。但不知何故 - 也许是因为惯用代码返回 空对象 ,其中明智或抛出异常以指示严重失败 - 我每月只会收到两次 AttributeError: 'NoneType' object has no attribute '...' 两次。

  4. 我认为这可能是一个错误。 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

from nullsafe import undefined, _

value = _(variable).method()
assert value is undefined
assert not value
assert value == None

Works with AttributeError and KeyError aswell

dic = {}
assert _(dic)["nah"] is undefined
assert _(dic).nah is undefined

The wrapped object typings will remain effective.


  1. No, there isn't.

  2. But to check for None, you don't write if x:, you write if x is None:. This is an important distinction - x evaluates to False for quite a few values that are propably perfectly valid (most notably 0-equivalent numbers and empty collections), whereas x is None only evaluates to True if the reference x points to the singleton object None.

  3. 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 an AttributeError: 'NoneType' object has no attribute '...' twice a month.

  4. 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 a UserProfile, it's not there and I get null 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?

爱已欠费 2024-10-06 20:22:03

首先,您的选项取决于您希望表达式在变量不可取消引用的情况下求值。我假设 None 是这些示例中的适当结果。

Python 中某些情况下的常见习惯用法是使用条件表达式:

variable.method() if variable is not None else None

虽然这种需求可能并不普遍,但在某些情况下它会很有用,特别是当引用是嵌套的并且您想要这样的东西时,该习惯用法很快就会变得很麻烦。

a?.b?.c?.d

请注意,支持用于安全引用的 ?. 运算符是 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:

variable.method() if variable is not None else None

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.

a?.b?.c?.d

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:

只有影子陪我不离不弃 2024-10-06 20:22:03

我已经在 Groovy 中使用过这个功能,所以我不会重复其他海报的 blub 悖论。

在 Groovy 中,像这样的语句

if(possiblyNull?.value){
    ...

在 Python 中执行此操作

try:
    testVar = possiblyNull.value
except:
    testVar = None
if(testVar): 

这绝对是 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

if(possiblyNull?.value){
    ...

Does this in Python

try:
    testVar = possiblyNull.value
except:
    testVar = None
if(testVar): 

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

二智少女 2024-10-06 20:22:03

假设您正在解析 xml,并且当前正在编写以下内容:

element = root.find("name")
name = "unnamed" if element is None else name.text

Python 3.8 引入了赋值表达式海象运算符)现在可以非常优雅地编写:

name = "unnamed" if (name := root.find("name")) is None else name.text

Let's say you're parsing xml, and you're currently writing this:

element = root.find("name")
name = "unnamed" if element is None else name.text

Python 3.8 introduced an assignment expression (the walrus operator) and can now write this pretty elegantly:

name = "unnamed" if (name := root.find("name")) is None else name.text
绝對不後悔。 2024-10-06 20:22:03

我见过并使用过的一个习惯用法是用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 yield False 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 with func(a, b, c) if callable(func) else [].

权谋诡计 2024-10-06 20:22:03

回答你的问题:是的,你需要编写 if-esle 子句,但使用 pythonic 方式:

variable.method() if variable else None

Answering your question: yeah, you need to write if-esle clause, but use the pythonic way:

variable.method() if variable else None
很酷不放纵 2024-10-06 20:22:03

这可能非常 hacky,但出于我的目的,这已经删除了一些代码:

from typing import Callable
def ch(func: Callable, _default = None):
   try:
      return func()
   except (AttributeError, KeyError):
     return _default

通过将您的调用包装在 lambda 中来使用它:

val = ch(lambda: obj['a']['b'].c[0].d(), 'default value')

This might be very hacky, but for my purposes this has cut out a bit of code:

from typing import Callable
def ch(func: Callable, _default = None):
   try:
      return func()
   except (AttributeError, KeyError):
     return _default

Use it by wrapping your call in a lambda:

val = ch(lambda: obj['a']['b'].c[0].d(), 'default value')
野生奥特曼 2024-10-06 20:22:03

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 special None 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 no null, there is no operator to deal with it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文