Ответы:
В Python объект 'null' является синглтоном None
.
Лучший способ проверить вещи на «Noneness» - это использовать оператор идентификации is
:
if foo is None:
...
None
, Питон ноль?Там нет null
в Python, а есть None
. Как уже говорилось, наиболее точный способ проверить, что что-то задано None
в качестве значения, - это использовать is
оператор тождества, который проверяет, что две переменные ссылаются на один и тот же объект.
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
None
None
является единственным экземпляром класса, NoneType
и любые дальнейшие попытки создания экземпляра этого класса будут возвращать тот же объект, который создает None
одиночный объект . Новички в Python часто видят сообщения об ошибках, которые упоминают NoneType
и задаются вопросом, что это такое. По моему личному мнению, эти сообщения можно просто назвать None
по имени, потому что, как мы скоро увидим, None
мало места для неопределенности. Поэтому, если вы видите какое-то TypeError
сообщение, в котором упоминается, что NoneType
это не может или не может, просто знайте, что это просто то None
, что использовалось таким образом, что это невозможно.
Кроме того, None
это встроенная константа, и как только вы запускаете Python, ее можно использовать везде, будь то в модуле, классе или функции. NoneType
напротив, нет, вам нужно сначала получить ссылку на него, запросив None
его класс.
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
Вы можете проверить None
уникальность с помощью функции идентичности Python id()
. Он возвращает уникальный номер, присвоенный объекту, каждый объект имеет один. Если 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
операторомПри написании кода у вас может возникнуть соблазн проверить на Единое, как это:
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
является "ложным", означающим, что если приведен к логическому значению, он вернется, False
а если применяется not
оператор, он вернется True
. Обратите внимание, что это не уникальное свойство None
. В дополнение к False
самому себе, свойство совместно используется пустыми списками, кортежами, наборами, комментариями, строками, а также 0 и всеми объектами из классов, которые реализуют __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()
Выше вы хотели вызывать, init_value()
когда значение установлено специально None
, или вы имели в виду, что значение 0
, или пустая строка, или пустой список также должны инициировать инициализацию. Как я уже сказал, будьте внимательны. Как это часто бывает в Python, явное лучше, чем неявное .
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 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:
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
используется только как действительное значениеЕсли вы обнаружите, что ваш код завален вышеуказанным try/except
шаблоном, чтобы просто различать None
флаги и None
данные, просто используйте другое тестовое значение. Существует шаблон, в котором значение, которое выходит за пределы набора допустимых значений, вставляется как часть данных в структуру данных и используется для контроля и проверки особых условий (например, границ, состояния и т. Д.). Такое значение называется часовым, и его можно использовать так None
же, как в качестве сигнала. Создание часового в Python тривиально.
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
Как я упоминал ранее, таможенные стражи идут с некоторыми оговорками. Во-первых, они не похожи на ключевые слова None
, поэтому python их не защищает. Вы можете перезаписать undefined
вышеизложенное в любое время, в любом месте модуля, в котором он определен, поэтому будьте осторожны с тем, как вы его используете и используете. Далее, экземпляр, возвращаемый object()
не одноэлементным, если вы сделаете этот вызов 10 раз, вы получите 10 различных объектов. Наконец, использование часового очень своеобразно. Часовой характерен для библиотеки, в которой он используется, и поэтому его область действия обычно должна быть ограничена внутренними компонентами библиотеки. Это не должно "вытекать" наружу. Внешний код должен узнавать об этом только в том случае, если их целью является расширение или дополнение API библиотеки.
Это не называется нулевым, как на других языках, но None
. Всегда есть только один экземпляр этого объекта, так что вы можете проверить эквивалентность с помощью x is None
(сравнения идентификаторов) вместо x == None
, если хотите.
None
. Тогда победят все умные люди, которые сравнивают друг с NoneType
другом!
В Python для представления отсутствия значения вы можете использовать значение None ( types.NoneType.None ) для объектов и "" (или len () == 0 ) для строк. Следовательно:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
Что касается разницы между "==" и "is", проверки на идентичность объекта с использованием "==" должно быть достаточно. Однако, поскольку операция «is» определяется как операция идентификации объекта, вероятно, более правильно использовать ее, а не «==». Не уверен, что есть даже разница в скорости.
В любом случае, вы можете взглянуть на:
0 == false
возврата в true
том, что оператор двойного равенства выполняет приведение типов. Однако с оператором тройного равенства 0 === false
возвращается false
, потому что «число» и «логическое значение» - это разные типы.
true
в условных выражениях . В Rust and Go 0
и false
есть разные типы, которые нельзя сравнивать на равенство.
Null - это особый тип объекта, такой как:
>>>type(None)
<class 'NoneType'>
Вы можете проверить, находится ли объект в классе 'NoneType':
>>>variable = None
>>>variable is None
True
Более подробная информация доступна на Python Docs
В соответствии со значением проверки Истины , None напрямую проверяется как FALSE, поэтому будет достаточно простейшего выражения:
if not foo:
True
для любого ложного значения, а не только None
.
egg is None
болееegg == None
: Последние могут быть перегружены, и, вероятно, ломаются при сравнении действительного объекта None (зависит от того, как это реализовано, но не ожидает , что все взять сравнения с None во внимание, не так ли?) , при этомis
всегда работает одинаково.