引用 Python 中的空对象 None,Python 的空值?基础知识 None在实践中
如何在Python中引用空对象?
如何在Python中引用空对象?
None
,Python 的空值?在Python中没有;取而代之的是.如前所述,测试某些内容是否已作为值给出的最准确方法是使用标识运算符,该运算符测试两个变量是否引用同一对象。null
None
None
is
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
None
None
是该类的唯一实例,任何进一步实例化该类的尝试都将返回相同的对象,这将形成一个单例。Python的新手经常看到提到并想知道它是什么的错误消息。我个人认为,这些信息可以简单地按名称提及,因为正如我们很快就会看到的那样,几乎没有歧义的余地。因此,如果您看到一些消息提到不能这样做或不能这样做,只要知道它只是以一种无法做到的方式使用的那个。NoneType
None
NoneType
None
None
TypeError
NoneType
None
此外,是一个内置常量。一旦你启动Python,它就可以从任何地方使用,无论是在模块,类还是函数中。 相比之下,不是,您需要首先通过查询其类来获取对它的引用。None
NoneType
None
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
您可以使用Python的恒等函数检查 的唯一性。它返回分配给对象的唯一编号,每个对象都有一个。如果两个变量的 id 相同,则它们实际上指向同一对象。None
id()
>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000
None
无法覆盖在更旧版本的Python(2.4之前)中,可以重新分配,但不能再分配了。甚至不能作为类属性或在函数的范围内。None
# In Python 2.7
>>> class SomeClass(object):
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to None
# In Python 3.5
>>> class SomeClass:
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to keyword
因此,可以安全地假设所有引用都是相同的。没有任何“自定义”。None
None
None
is
在编写代码时,您可能会想像这样测试Noneness:
if value==None:
pass
或者测试这样的谎言
if not value:
pass
您需要了解其含义以及为什么明确表达通常是一个好主意。
None
为什么这样做
value is None
而不是
value==None
?
第一个等效于:
id(value)==id(None)
而表达式实际上是这样应用的value==None
value.__eq__(None)
如果价值真的是,那么你会得到你所期望的。None
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
在大多数情况下,结果将是相同的,但该方法打开了一扇门,使任何准确性保证都无效,因为它可以在类中被重写以提供特殊行为。__eq__()
请考虑此类。
>>> class Empty(object):
... def __eq__(self, other):
... return not other
所以你试穿它,它的工作原理None
>>> empty = Empty()
>>> empty==None
True
但是,它也适用于空字符串
>>> empty==''
True
而
>>> ''==None
False
>>> empty is None
False
None
以下两项测试
if value:
# Do something
if not value:
# Do something
实际上被评估为
if bool(value):
# Do something
if not bool(value):
# Do something
None
是一个“falsey”,这意味着如果转换为布尔值,它将返回,如果应用运算符,它将返回 。但请注意,它不是 所独有的属性。除了自身之外,该属性还由空列表、元组、集合、字典、字符串以及 0 以及实现 magic 方法返回 的类中的所有对象共享。False
not
True
None
False
__bool__()
False
>>> bool(None)
False
>>> not None
True
>>> bool([])
False
>>> not []
True
>>> class MyFalsey(object):
... def __bool__(self):
... return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True
因此,在按以下方式测试变量时,请特别注意要在测试中包含或排除的内容:
def some_function(value=None):
if not value:
value = init_value()
在上面,您的意思是在将值专门设置为 时调用,还是说值设置为 、或空字符串或空列表也应触发初始化?就像我说的,要注意。通常情况下,在Python中,显式比隐式更好。init_value()
None
0
None
在实践中None
用作信号值None
在Python中具有特殊状态。它是最受欢迎的基线值,因为许多算法将其视为异常值。在这种情况下,它可以用作标志,以指示条件需要一些特殊处理(例如默认值的设置)。
您可以分配给函数的关键字参数,然后显式测试它。None
def my_function(value, param=None):
if param is None:
# Do something outrageous!
在尝试获取对象的属性时,可以将其作为默认值返回,然后在执行特殊操作之前显式测试它。
value = getattr(some_obj, 'some_attribute', None)
if value is None:
# do something spectacular!
默认情况下,当尝试访问不存在的键时,字典的方法会返回:get()
None
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
如果您尝试使用下标表示法访问它,则会引发KeyError
>>> value = some_dict['foo']
KeyError: 'foo'
同样,如果您尝试弹出一个不存在的项目
>>> value = some_dict.pop('foo')
KeyError: 'foo'
您可以使用通常设置为None
value = some_dict.pop('foo', None)
if value is None:
# Booom!
None
同时用作标志和有效值上面描述的用法是,当它不被认为是一个有效值时,它更像是一个做一些特殊事情的信号。然而,在某些情况下,有时知道来自哪里很重要,因为即使它被用作信号,它也可能是数据的一部分。None
None
当您通过回退查询对象的属性时,不会告诉您尝试访问的属性是否已设置为,或者该对象是否完全不存在该属性。从字典访问密钥时,情况相同,例如 ,您不知道是否丢失,或者是否只是设置为 。如果您需要该信息,通常的处理方法是直接尝试从构造中访问属性或键:getattr(some_obj, 'attribute_name', None)
None
None
some_dict.get('some_key')
some_dict['some_key']
None
try/except
try:
# Equivalent to getattr() without specifying a default
# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute
# Now you handle `None` the data here
if value is None:
# Do something here because the attribute was set to None
except AttributeError:
# We're now handling the exceptional situation from here.
# We could assign None as a default value if required.
value = None
# In addition, since we now know that some_obj doesn't have the
# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
与 dict 类似:
try:
value = some_dict['some_key']
if value is None:
# Do something here because 'some_key' is set to None
except KeyError:
# Set a default
value = None
# And do something because 'some_key' was missing
# from the dict.
log_something(some_dict)
上面的两个示例显示了如何处理对象和字典情况。功能呢?同样的事情,但是我们使用双星号关键字参数来达到这个目的:
def my_function(**kwargs):
try:
value = kwargs['some_key']
if value is None:
# Do something because 'some_key' is explicitly
# set to None
except KeyError:
# We assign the default
value = None
# And since it's not coming from the caller.
log_something('did not receive "some_key"')
None
仅用作有效值如果您发现您的代码中充斥着上述模式,只是为了区分标志和数据,那么只需使用另一个测试值即可。有一种模式,其中落在有效值集之外的值作为数据结构中数据的一部分插入,并用于控制和测试特殊条件(例如边界,状态等)。这样的值称为哨兵,它可以用作信号的方式。在Python中创建一个哨兵是微不足道的。try/except
None
None
None
undefined = object()
上面的对象是唯一的,不会做任何可能对程序感兴趣的事情,因此它是作为标志的绝佳替代品。一些警告适用,在代码之后有更多关于此的信息。undefined
None
带功能
def my_function(value, param1=undefined, param2=undefined):
if param1 is undefined:
# We know nothing was passed to it, not even None
log_something('param1 was missing')
param1 = None
if param2 is undefined:
# We got nothing here either
log_something('param2 was missing')
param2 = None
带字典
value = some_dict.get('some_key', undefined)
if value is None:
log_something("'some_key' was set to None")
if value is undefined:
# We know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value = None
使用对象
value = getattr(obj, 'some_attribute', undefined)
if value is None:
log_something("'obj.some_attribute' was set to None")
if value is undefined:
# We know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value = None
正如我之前提到的,自定义哨兵有一些警告。首先,它们不是像 这样的关键字,所以Python不会保护它们。您可以随时在定义的模块中的任何位置覆盖上述内容,因此请小心如何公开和使用它们。接下来,返回的实例不是单例。如果你拨打这个电话10次,你会得到10个不同的对象。最后,哨兵的使用是非常特殊的。哨兵特定于使用它的库,因此其范围通常应限制在库的内部。它不应该“泄漏”出来。只有当外部代码的目的是扩展或补充库的API时,它们才应该意识到这一点。None
undefined
object()