null object in Python?
如何在Python中引用空对象?
在python中,"null"对象是singleton
检查事物是否"不存在"的最佳方法是使用身份操作符
1 2 | if foo is None: ... |
python中没有
1 2 3 4 5 | >>> foo is None True >>> foo = 'bar' >>> foo is None False |
基础知识有且只能有一个
另外,
1 2 3 4 | >>> NoneType NameError: name 'NoneType' is not defined >>> type(None) NoneType |
您可以使用python的标识函数
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> 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 |
不能覆盖
在更旧版本的python(2.4之前)中,可以重新分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 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 |
因此,可以安全地假设所有
在编写代码时,您可能会尝试测试这样的不存在性:好的。
1 2 | if value==None: pass |
或者像这样测试错误好的。
1 2 | if not value: pass |
你需要理解其中的含义以及为什么直截了当往往是个好主意。好的。案例1:测试值是否为
为什么这样做好的。
1 | value is None |
而不是好的。
1 | value==None |
第一个相当于:好的。
1 | id(value)==id(None) |
而
1 | value.__eq__(None) |
如果值真的是
1 2 3 | >>> nothing = function_that_does_nothing() >>> nothing.__eq__(None) True |
在大多数常见的情况下,结果都是一样的,但是
考虑这个类。好的。
1 2 3 | >>> class Empty(object): ... def __eq__(self, other): ... return not other |
所以你在
1 2 3 | >>> empty = Empty() >>> empty==None True |
但它也适用于空字符串好的。
1 2 | >>> empty=='' True |
然而好的。
1 2 3 4 | >>> ''==None False >>> empty is None False |
案例2:使用
以下两个测试好的。
1 2 3 4 5 | if value: # do something if not value: # do something |
实际评估为好的。
1 2 3 4 5 | if bool(value): # do something if not bool(value): # do something |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> 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 |
因此,当以以下方式测试变量时,要特别注意测试中包含或排除的内容:好的。
1 2 3 | def some_function(value=None): if not value: value = init_value() |
在上面,您是指当值专门设置为
您可以将
1 2 3 | def my_function(value, param=None): if param is None: # do something outrageous! |
当试图获取对象的属性时,可以将其作为默认值返回,然后在执行特殊操作之前显式测试它。好的。
1 2 3 | value = getattr(some_obj, 'some_attribute', None) if value is None: # do something spectacular! |
默认情况下,当试图访问不存在的密钥时,字典的
1 2 3 4 | >>> some_dict = {} >>> value = some_dict.get('foo') >>> value is None True |
如果您试图使用下标符号访问它,那么会引发
1 2 | >>> value = some_dict['foo'] KeyError: 'foo' |
同样,如果尝试弹出一个不存在的项好的。
1 2 | >>> value = some_dict.pop('foo') KeyError: 'foo' |
您可以使用通常设置为
1 2 3 | value = some_dict.pop('foo', None) if value is None: # booom! |
上述
当使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 hanling 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类似:好的。
1 2 3 4 5 6 7 8 9 10 | 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) |
上面的两个例子说明了如何处理对象和字典的情况,函数呢?同样的,但是我们使用了双星号关键字参数:好的。
1 2 3 4 5 6 7 8 9 10 11 | 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"') |
如果您发现您的代码中到处都是上述
1 | undefined = object() |
上面的
具有功能好的。
1 2 3 4 5 6 7 8 9 10 11 | 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 |
用DICT好的。
1 2 3 4 5 6 7 8 | 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 |
带有对象好的。
1 2 3 4 5 6 7 | 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中,为了表示缺少值,可以对对象使用none值(types.nonetype.none),对字符串使用"(或len()==0")。因此:
1 2 3 4 5 | if yourObject is None: # if yourObject == None: ... if yourString =="": # if yourString.len() == 0: ... |
对于"=="和"is"之间的差异,使用"=="测试对象标识就足够了。但是,由于操作"is"被定义为对象标识操作,因此使用它可能更正确,而不是"=="。不确定是否有速度差。
不管怎样,你可以看看:
- python内置常量文档页。
- python真值测试文档页。
根据真值测试,"无"直接测试为假,因此最简单的表达式将满足:
1 | if not foo: |