None和<no value>的区别

3

我熟悉Java的null和C++的nullptr,还有几种脚本语言中类似的概念。None看起来非常像Python中的那个旧主题。

然后我遇到了这个函数声明:

 numpy.amin(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

None<no value>有什么区别?我猜想这只是在没有定义默认值时生成文档的一个方式,但为什么不完全不列出默认值呢?


您可以查看源代码,您会发现他们创建了自己的_NoValue对象(很可能是通过_NoValue = object()实现的)。他们需要这样做是因为任何值都是合理的,包括None,因此需要一个单独的对象来指示用户未提供值(因为在函数中无法区分)。因此,确实,<no value>是文档目的的特殊表示。 - a_guest
1
@a_guest:它是一个自定义类,其行为与None非常相似,并具有有用的repr()链接 - Martijn Pieters
2个回答

8

这只是一份文件记录,Python本身并没有这样的概念。

请注意,None本身也是一个有效的对象。有时你想要将None作为参数的有效值,因此不能将其用作可选参数的默认值。你无法区分默认值None和显式传递的None,因为它是一个单例!

如果我需要定义这样的函数,我会使用其他单例哨兵。你可以从任何东西创建一个,但最简单的方法是使用一个object()实例:

_sentinel = object()

def foo(bar, baz=_sentinel):
    if baz is not _sentinel:
        # baz has a defined value, because it is
        # not a reference to the sentinel

也许我在文档中还会使用<no value>来表示baz是可选的。这完全取决于当地的惯例。例如,Python文档本身在可选参数周围使用[...]

numpy.amin()实际上是一个代理函数;它将实际工作委托给numpy.minimum()(通过ufunc.reduce()),或者如果第一个参数是实现了amin()方法的子类,则委托给子类的该方法。由于后者应该能够设置自己的默认值,使用标志让numpy.amin()实现只传递那些实际给定了显式值的关键字参数,而不指定子类.amin()实现应该使用什么样的标志或接受什么类型。

Numpy项目实际上创建了自己的单例类作为标志,以便为对象提供有用的repr()输出:

>>> from numpy._globals import _NoValue
>>> _NoValue
<no value>
>>> type(_NoValue)
<class 'numpy._globals._NoValueType'>

最后,None 不应该与 nullnullptr 进行比较。 None 是一个单例对象,是一种可用于引用而非其他对象的东西。而 nullnullptr 用于表示没有引用,可以像其他标量值一样传递。在 Python 中,你无法这样做,因为所有东西都是一个有效的对象引用。最多,如果您尝试在其命名空间中使用尚未绑定到名称的名称,则会获得 NameErrorUnboundLocal 异常。

1
“在Python中,您无法创建空引用。” - 但是,在某种程度上是可以的。在将值分配给它们之前,本地变量是空引用,或者如果您使用del删除了它们的值。但是,您不能像使用nullnullptr那样在Python中传递和操作空引用。 - user2357112
1
@user2357112supportsMonica: 你不能将它们传递出去。否则你会得到一个“UnboundLocal”异常。 - Martijn Pieters
例如 numpy.amin() 函数中,只有在未使用默认值时,keepdims 参数的值才会传递给 a.amin() 函数。因为 a 可以是 numpy.ndarray 的任何子类,所以如果 None 有任何特定含义,这取决于您传递的确切数组类型。开发人员不想限制可以使用哪些值,也不想防止这些类型选择不同的默认值。 - Martijn Pieters
如果“null”表示引用的缺失,那么为什么它被称为“null reference”?这听起来像是一个引用。我不明白你所描述的区别。在Python中你不能做什么?也就是说,Java代码是什么样子的? - Kelly Bundy
@HeapOverflow:这是一个常见的简化。 - Martijn Pieters
显示剩余6条评论

2

np._NoValue类的代码:

class _NoValueType(object):
    """Special keyword value.

    The instance of this class may be used as the default value assigned to a
    deprecated keyword in order to check if it has been given a user defined
    value.
    """
    __instance = None
    def __new__(cls):
        # ensure that only one instance exists
        if not cls.__instance:
            cls.__instance = super(_NoValueType, cls).__new__(cls)
        return cls.__instance

    # needed for python 2 to preserve identity through a pickle
    def __reduce__(self):
        return (self.__class__, ())

    def __repr__(self):
        return "<no value>"
File:           /usr/local/lib/python3.6/dist-packages/numpy/_globals.py
Type:           type

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接