нулевой объект в Python?



Как я могу ссылаться на нулевой объект в Python?

977   5  

5 ответов:

в Python объект' null ' является синглтоном None.

лучший способ проверить вещи на "несущественность" - использовать оператор идентификации, is:

if foo is None:
    ...

это не называется null, как в других языках, но None. Всегда есть только один экземпляр этого объекта, поэтому вы можете проверить эквивалентность с x is None (сравнение идентичности) вместо x == 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

вы должны понять последствия и почему это часто хорошая идея, чтобы быть явным.

Случай 1: проверка, если значение 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

Случай 2: Использование None логическое

следующие два теста

if value:
    # do something

if not value:
    # do something

фактически оцениваются как

if bool(value):
    # do something

if not bool(value):
    # do something

None это "falsey", что означает, что если приведено к логическому значению, оно вернет False и если использовать not оператор он вернет True. Обратите внимание, однако, что это не уникальное свойство None. В дополнение к свойство является общим для пустых списков, кортежей, множеств, предсказывает, струны, а также 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)

в приведенных выше двух примерах показано, как обрабатывать объектные и словарные случаи, а как насчет функций? То же самое, но мы используем аргумент ключевого слова double asterisks для этой цели:

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()

The 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 библиотеки.

в Python, чтобы представить отсутствие значения, вы можете использовать нет значение (типы.NoneType.Нет) для объектов и "" (или len () = = 0) для строк. Таким образом:

if yourObject is None:  # if yourObject == None:
    ...

if yourString == "":  # if yourString.len() == 0:
    ...

Что касается разницы между "==" и "is", тестирование идентичности объекта с использованием "==" должно быть достаточным. Однако, поскольку операция " is " определяется как операция идентификации объекта, вероятно, правильнее использовать ее, а не "== " . Не уверен, что есть даже разница в скорости.

в любом случае, вы можете посмотреть на:

на проверка истинности,' None ' напрямую проверяет как FALSE, поэтому достаточно простого выражения:

if not foo:

Comments

    Ничего не найдено.