id () против оператора `is`. Безопасно ли сравнивать идентификаторы? Означает ли один и тот же `id` один и тот же объект? - PullRequest
0 голосов
/ 11 сентября 2018

Насколько я могу положиться на id() объекта и его уникальность на практике? E.g.:

  • Означает ли id(a) == id(b) a is b или наоборот? А как же наоборот?
  • Насколько безопасно сохранять id где-нибудь для последующего использования (например, в каком-то реестре вместо самого объекта)?

(Записано как предлагаемый канонический ответ на Канонические выражения для Python: объекты с одинаковым id () - один и тот же объект, оператор `is`, объекты несвязанного метода )

1 Ответ

0 голосов
/ 11 сентября 2018

Согласно документации id() , id гарантированно будет уникальным

  1. за время жизни конкретного объекта и
  2. в конкретном экземпляре интерпретатора

Таким образом, сравнение id s небезопасно, если только вы не гарантируете, что оба объекта, чьи id s взяты, все еще живы во время сравнения (и связаны с тем же Экземпляр интерпретатора Python, но вам нужно постараться, чтобы это стало ложным).

Именно это и делает is, что делает сравнение id излишним. Если по какой-либо причине вы не можете использовать синтаксис is, всегда есть operator.is_.


Теперь, , является ли объект еще живым во время сравнения, не всегда очевидно (а иногда и не -очевидный):

  • Доступ к некоторым атрибутам (например, привязанные методы объекта ) каждый раз создает новый объект. Таким образом, результат id может или может не совпадать при доступе к каждому атрибуту.

    * * Пример тысячу сорок четыре: * * 1045
    >>> class C(object): pass
    >>> c=C()
    >>> c.a=1
    
    >>> c.a is c.a
    True        # same object each time
    
    >>> c.__init__ is c.__init__
    False       # a different object each time
    
    # The above two are not the only possible cases.
    # An attribute may be implemented to sometimes return the same object
    # and sometimes a different one:
    @property
    def page(self):
        if check_for_new_version():
            self._page=get_new_version()
        return self._page
    
  • Если объект создан в результате вычисления выражения и нигде не сохранен, он немедленно отбрасывается, 1 и любой объект, созданный после этого, может занять его id.

    • Это верно даже для одной строки кода. Например. результат id(create_foo()) == id(create_bar()) не определен.

      * * Пример тысяча шестьдесят один:
      >>> id([])     #the list object is discarded when id() returns
      39733320L
      >>> id([])     #a new, unrelated object is created (and discarded, too)
      39733320L      #its id can happen to be the same
      >>> id([[]])
      39733640L      #or not
      >>> id([])
      39733640L      #you never really know
      

Из-за вышеуказанных требований безопасности при сравнении id с сохранение id вместо объекта не очень полезно, так как в любом случае необходимо сохранить ссылку на сам объект - чтобы гарантировать, что он остается живым. Также нет никакого увеличения производительности: реализация is так же проста, как сравнение указателей .


Наконец, в качестве внутренней оптимизации (и деталей реализации, так что она может отличаться в разных реализациях и выпусках), CPython повторно использует некоторые часто используемые простые объекты неизменяемых типов. На момент написания статьи это включает маленькие целые числа и некоторые строки . Поэтому, даже если вы получили их из разных мест, их id могут совпадать.

Это (технически) не нарушает вышеприведенных id() обещаний уникальности документации: повторно используемый объект остается живым в течение всех повторных использований.

Это также не имеет большого значения, потому что, если две переменные указывают на один и тот же объект или нет, практично знать, является ли объект изменчивым: если две переменные указывают на один и тот же изменяемый объект, мутирует одна (неожиданно) ) поменяй другой тоже . Неизменяемые типы не имеют такой проблемы, поэтому для них не имеет значения, указывают ли две переменные на два идентичных объекта или на один и тот же.


1 Иногда это называется "неназванное выражение".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...