Відповіді:
У Python об'єктом 'null' є синглтон None.
Найкращий спосіб перевірити речі на "Noneness" - це використовувати оператор ідентифікації is:
if foo is None:
...
None, Нуль Python?У nullPython немає , натомість є 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(). Він повертає унікальний номер, присвоєний об'єкту, кожен об'єкт має його. Якщо ідентифікатор двох змінних однаковий, вони фактично вказують на один і той же об'єкт.
>>> 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завжди працює те саме.