Оператор «is» Python ведет себя неожиданно с целыми числами?
blockquote>Вкратце - позвольте мне подчеркнуть: Не используйте
is
для сравнения целых чисел.Это не поведение, о котором вы должны ожидать.
Вместо этого используйте
==
и!=
для сравнения для равенства и неравенства соответственно. Например:>>> a = 1000 >>> a == 1000 # Test integers like this, True >>> a != 5000 # or this! True >>> a is 1000 # Don't do this! - Don't use `is` to test integers!! False
Объяснение
Чтобы это знать, вам нужно знать следующее.
Во-первых, что делает
is
? Это оператор сравнения. Из документации :Операторы
blockquote>is
иis not
проверяют идентификатор объекта:x is y
истинно тогда и только тогда, когда x и y являются одинаковыми объект.x is not y
дает обратное значение истины.И поэтому следующие эквиваленты.
>>> a is b >>> id(a) == id(b)
blockquote>
id
Вернуть «идентификатор» объекта. Это целое число (или длинное целое число), которое гарантировано будет уникальным и постоянным для этого объекта в течение его жизни. Два объекта с неперекрывающимся временем жизни могут иметь одинаковое значениеid()
.Обратите внимание, что тот факт, что идентификатор объекта в CPython (эталонная реализация Python) - это местоположение в память - это деталь реализации. Другие реализации Python (например, Jython или IronPython) могут легко иметь другую реализацию для
id
.Итак, каков прецедент для
is
? PEP8 описывает :. Сравнение с синглонами типа
None
всегда должно выполняться с помощьюis
илиis not
, никогда не выполняемых операторов равенства.Вопрос
Вы задаете и задаете следующий вопрос (с кодом):
Почему в Python происходит непредвиденное поведение?
blockquote>>>> a = 256 >>> b = 256 >>> a is b True # This is an expected result
Ожидаемый результат not . Почему это ожидалось? Это означает, что целые числа, оцененные в
256
, на которые ссылаются какa
, так иb
, являются одним и тем же экземпляром целого числа. Целые числа неизменны в Python, поэтому они не могут измениться. Это не должно влиять на какой-либо код. Этого нельзя ожидать. Это всего лишь деталь реализации.Но, возможно, мы должны быть рады, что каждый отдельный экземпляр в памяти не будет каждый раз, когда мы укажем, что значение равно 256.
blockquote>>>> a = 257 >>> b = 257 >>> a is b False # What happened here? Why is this False?
Looks например, теперь у нас есть два отдельных экземпляра целых чисел со значением
257
в памяти. Поскольку целые числа неизменны, это отнимает память. Будем надеяться, что мы не будем тратить много денег. Наверное, нет. Но это поведение не гарантируется.blockquote>>>> 257 is 257 True # Yet the literal numbers compare properly
Ну, похоже, что ваша конкретная реализация Python пытается быть умной и не создавать избыточно ценные целые числа в памяти, если только она не имеет к. Вы, кажется, указываете, что используете референтную реализацию Python, которая является CPython. Хорошо для CPython.
Возможно, было бы лучше, если бы CPython мог сделать это глобально, если бы он мог сделать это дешево (так как это будет стоить в поиске), возможно, другая реализация.
Но что касается влияния на код, вам все равно, является ли целое число конкретным экземпляром целого числа. Вы должны знать, что такое значение этого экземпляра, и вы использовали бы для этого обычные операторы сравнения, т. Е.
==
.Что
is
делает
is
проверяет, чтоid
двух объектов одинаковы. В CPythonid
- это место в памяти, но это может быть какое-то другое уникально идентифицирующее число в другой реализации. Чтобы переформулировать это с помощью кода:>>> a is b
совпадает с
>>> id(a) == id(b)
Почему мы хотели бы использовать
is
тогда?Это может быть очень быстрой проверкой, чтобы сказать, проверяя, являются ли две очень длинные строки равными по стоимости. Но поскольку это относится к уникальности объекта, мы, таким образом, имеем ограниченные прецеденты. Фактически, мы в основном хотим использовать его для проверки на
None
, который является одноэлементным (единственный экземпляр, существующий в одном месте в памяти). Мы могли бы создать другие синглтоны, если есть потенциал для их объединения, что мы можем проверить с помощьюis
, но они относительно редки. Вот пример (будет работать в Python 2 и 3), напримерSENTINEL_SINGLETON = object() # this will only be created one time. def foo(keyword_argument=None): if keyword_argument is None: print('no argument given to foo') bar() bar(keyword_argument) bar('baz') def bar(keyword_argument=SENTINEL_SINGLETON): # SENTINEL_SINGLETON tells us if we were not passed anything # as None is a legitimate potential argument we could get. if keyword_argument is SENTINEL_SINGLETON: print('no argument given to bar') else: print('argument to bar: {0}'.format(keyword_argument)) foo()
Что печатает:
no argument given to foo no argument given to bar argument to bar: None argument to bar: baz
Итак, мы видим, что с
is
и дозорным, мы могут различать, когдаbar
вызывается без аргументов и когда он вызывается с помощьюNone
. Это первичные варианты использования дляis
- do not использовать его для проверки равенства целых чисел, строк, кортежей или других подобных вещей.
На блоге я читал об этом (я, может казаться, не нахожу URL), он был указан: инструкции по платформе базируются и развиты из инструкций C++ (они - все закаленные разработчики C++), в то время как инструкции stylecop обеспечивают, более современный новый C# только инструкции... Оба в порядке, принимают решение самостоятельно... Я лично использую StyleCop
Мы используем StyleCop для всего нашего кода, и кроме некоторых незначительных придирается, большинство его стандартов, я чувствую вывод к самому читаемому коду. Много его стандартов было в большой степени обсуждено в Microsoft и имело обратную связь от сообщества, и в то время как не ожидается, что все согласятся со всем, это, вероятно, о лучшем 'стандарте' существует (особенно, поскольку это позволяет автоматическую проверку и автоматическое исправление с StyleCop для плагина ReSharper).
, Если существуют какие-либо вещи, Вы категорически не согласны с, Jason Allor, который поддерживает инструмент, довольно открыт для предложений вокруг определенных вещей, например, с автосвойствами StyleCop, на которых первоначально настаивают...
public int Prop
{
get;
set;
}
..., но мы повысили запрос на изменение разрешить однострочные свойства (т.е. все на одной строке), поскольку это не менее читаемо и занимает меньше места. Он внес это изменение в течение нескольких дней.
Вы принимаете решение. Если Вам нравятся некоторые части один и некоторые части другого, запишите свое собственное руководство по стилю. Если Вам нравится один лучше, чем другой, выберите его.
существенная вещь сделать состоит в том, чтобы выбрать стиль; нет никакого способа оценить один по другому любым строгим количественным способом.
Эта статья команды stylecop объясняет именно то, что вы спрашиваете, я думаю. http://blogs.msdn.com/sourceanalysis/archive/2008/05/25/a-difference-of-style.aspx
И чтобы ответить на вторую часть вашего вопроса, наша команда только начала использовать StyleCop использует все правила (некоторые люди выбирают, какие из них использовать). Единственное, что мне не нравится, это дополнительное время, которое требуется, но использование такого инструмента, как StyleCopForResharper, делает его намного быстрее. Раньше меня раздражало, когда люди писали код, который выглядел не так, как я бы, но теперь, когда мы используем StyleCop, код каждого выглядит одинаково. Больше не нужно кусать губу о раздражающих вещах, которые делают люди