Ответы:
В 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
NoneNoneявляется единственным экземпляром класса, 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всегда работает одинаково.