Відповіді:
У Python об'єктом 'null' є синглтон None
.
Найкращий спосіб перевірити речі на "Noneness" - це використовувати оператор ідентифікації is
:
if foo is None:
...
None
, Нуль Python?У 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()
. Він повертає унікальний номер, присвоєний об'єкту, кожен об'єкт має його. Якщо ідентифікатор двох змінних однаковий, вони фактично вказують на один і той же об'єкт.
>>> 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
є "фальсією", що означає, що якщо присвоєно булевому значенню, воно повернеться, 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
Якщо ви намагаєтеся отримати доступ до нього за допомогою позначення підписки, a 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 бібліотеки.
Це не називається null, як в інших мовах, але 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:
...
Щодо різниці між "==" та "є", тестування на предмет об'єкта з використанням "==" повинно бути достатнім. Однак, оскільки операція "є" визначається як операція ідентичності об'єкта, ймовірно, правильніше використовувати її, а не "==". Не впевнений, чи є навіть різниця швидкостей.
У будь-якому випадку, ви можете подивитися:
0 == false
повертається true
через те, що оператор з подвійним рівнем вводить примус. Однак оператор з потрійними рівняннями 0 === false
повертається false
, оскільки "число" та "булеве" різні типи.
true
у умовних умовах. У Іржа і Go, 0
і false
різні типи , які не можуть бути порівняні для рівності.
Null - це особливий тип об'єкта, як:
>>>type(None)
<class 'NoneType'>
Ви можете перевірити, чи є об’єкт у класі "NoneType":
>>>variable = None
>>>variable is None
True
Більше інформації можна отримати в Python Docs
За тестування значення Істини «None» прямо не перевіряє , як FALSE, так що простий вислів буде досить:
if not foo:
True
для будь-якого falsy значення, а не тільки None
.
egg is None
більшegg == None
: Останні можуть бути перевантажені, і, ймовірно, ламаються при порівнянні дійсного об'єкта None (залежить від того, як це реалізовано, але не очікує , що все взяти порівняння з None до уваги, що не так чи що?) , хочаis
завжди працює те саме.