С new_list = my_list
у вас фактически нет двух списков. Назначение просто копирует ссылку на список, а не фактический список, поэтому оба new_list
и my_list
относятся к тому же списку после назначения.
Чтобы на самом деле скопировать список, у вас есть различные возможности :
list.copy()
(доступный с python 3.3): new_list = old_list.copy()
new_list = old_list[:]
мнение Алексея Мартелли (по крайней мере, в 2007 году ) об этом означает, что это странный синтаксис, и нет смысла использовать его когда-либо . ;) (По его мнению, следующий более читабель). list()
: new_list = list(old_list)
copy.copy()
: import copy
new_list = copy.copy(old_list)
Это немного медленнее, чем list()
, потому что сначала он должен узнать тип данных old_list
. copy.deepcopy()
: import copy
new_list = copy.deepcopy(old_list)
Очевидно, самый медленный и самый необходимый для памяти способ, но иногда неизбежный. Пример:
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return str(self.val)
foo = Foo(1)
a = ['foo', foo]
b = a.copy()
c = a[:]
d = list(a)
e = copy.copy(a)
f = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print('original: %r\n list.copy(): %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r'
% (a, b, c, d, e, f))
Результат:
original: ['foo', 5, 'baz']
list.copy(): ['foo', 5]
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]
Я был членом комитета IEEE-754, я попытаюсь немного разъяснить некоторые вещи.
Во-первых, числа с плавающей запятой не являются действительными числами, а арифметика с плавающей запятой не удовлетворяют аксиомам реальной арифметики. Трихотомия - это не единственное свойство реальной арифметики, которое не выполняется для поплавков и даже самое важное. Например:
Я мог бы продолжить. Невозможно указать арифметический тип фиксированного размера, который удовлетворяет всем свойствам реальной арифметики, которые мы знаем и любим. Комитет 754 должен решить склонить или сломать некоторые из них. Это руководство основано на некоторых довольно простых принципах:
Что касается вашего комментария, «это не означает, что правильный ответ ложный», это неправильно. Предикат (y < x)
спрашивает, меньше ли y
, чем x
. Если y
является NaN, то это не меньше любого значения с плавающей запятой x
, поэтому ответ обязательно является ложным.
Я упомянул, что трихотомия не выполняется для значений с плавающей запятой. Однако есть аналогичное свойство, которое выполняется. Пункт 5.11, параграф 2 стандарта 754-2008:
Возможны четыре взаимоисключающих отношения: меньше, равно, больше и неупорядочено. Последний случай возникает, когда хотя бы один операнд - NaN.
blockquote>Что касается написания дополнительного кода для обработки NaNs, обычно возможно (хотя и не всегда легко) структурировать ваш код в таком формате, что NaNs проваливаются должным образом, но это не всегда так. Когда это не так, может потребоваться некоторый дополнительный код, но это небольшая цена, чтобы заплатить за удобство, которое привело к алгебраическому закрытию для арифметики с плавающей запятой.
Приложение: Многие комментаторы утверждали, что было бы более полезно сохранить рефлексивность равенства и трихотомии на том основании, что принятие NaN! = NaN, похоже, не сохраняет какой-либо знакомой аксиомы. Я признаюсь, что имею некоторое сочувствие к этой точке зрения, поэтому я решил вернуться к этому ответу и предоставить немного больше контекста.
Мое понимание от разговоров с Каханом заключается в том, что NaN! = NaN возникла из двух прагматических соображений :
- То, что
x == y
должно быть эквивалентноx - y == 0
, когда это возможно (не являясь теоремой реальной арифметики, это делает аппаратную реализацию сравнения более эффективной с точки зрения пространства, что имеет первостепенное значение при время, когда стандарт был разработан - обратите внимание, однако, что это нарушается при x = y = бесконечность, поэтому это не является большой причиной для себя, оно может быть разумно согнуто до(x - y == 0) or (x and y are both NaN)
).- Что еще более важно, предикат
isnan( )
не существовал в то время, когда NaN был формализован в арифметике 8087; необходимо было предоставить программистам удобное и эффективное средство обнаружения значений NaN, которые не зависят от языков программирования, предоставляющих нечто вродеisnan( )
, которое может занять много лет. Я процитирую собственное письмо Кахана по этому вопросу:Если бы не было способа избавиться от NaN, они были бы столь же бесполезны, как и Indefinites на CRAY; как только кто-то столкнулся, расчет лучше всего прекратить, а не продолжиться на неопределенное время до окончательного вывода. Вот почему некоторые операции над NaN должны доставлять результаты, отличные от NaN. Какие операции? ... Исключениями являются предикаты C «x == x» и «x! = X», которые соответственно равны 1 и 0 для каждого бесконечного или конечного числа x, но наоборот, если x не является числом (NaN); они обеспечивают единственное простое исключающее различие между NaN и числами на языках, которым не хватает слова для NaN и предиката IsNaN (x).
blockquote>Обратите внимание, что это также логика, которая исключает возвращение чего-либо как «Not-A-Boolean». Возможно, этот прагматизм был неуместным, и стандарт должен был потребовать
isnan( )
, но это сделало бы NaN почти невозможным использовать эффективно и удобно в течение нескольких лет, пока мир ждал принятия языка программирования. Я не уверен, что это был бы разумный компромисс.Чтобы быть тупым: результат NaN == NaN теперь не изменится. Лучше научиться жить с ним, чем жаловаться в Интернете. Если вы хотите утверждать, что отношение порядка, подходящее для контейнеров, должно существовать также , я бы рекомендовал, чтобы ваш любимый язык программирования реализовал предикат
totalOrder
, стандартизованный в IEEE-754 (2008). Тот факт, что он еще не говорит о справедливости озабоченности Кахана, которая мотивировала нынешнее положение дел.
NaN можно рассматривать как неопределенное состояние / число. аналогично понятию 0/0, которое не определено или sqrt (-3) (в системе реальных чисел, где живет плавающая точка).
NaN используется как своего рода заполнитель для этого неопределенного состояния. Математически говоря, undefined не равен undefined. Вы также не можете сказать, что неопределенное значение больше или меньше другого неопределенного значения. Поэтому все сравнения возвращают false.
Это поведение также выгодно в случаях, когда вы сравниваете sqrt (-3) с sqrt (-2). Они оба вернут NaN, но они не эквивалентны, даже если они возвращают одинаковое значение. Поэтому, когда равенство всегда возвращает false при работе с NaN, это желаемое поведение.
!=
возвращает true. Если возвращать false NaN==NaN
и NaN!=NaN
, то код, который сравнивает x и y, будет выбирать, что должно происходить, когда оба операнда являются NaN, выбирая либо ==
, либо !=
.
– supercat
10 October 2013 в 03:10
Я предполагаю, что NaN (Not A Number) означает именно это: это не число, и поэтому сравнение его действительно не имеет смысла.
Это немного похоже на арифметику в SQL с null
: все они приводят к null
.
Сравнение чисел с плавающей запятой сравнивает числовые значения. Таким образом, они не могут использоваться для не числовых значений. Таким образом, NaN нельзя сравнивать в цифровом смысле.
FOO
. Для того чтобы NaN быть эквивалентным if (NaN != NaN) foo();
, не следует выполнять foo
, но это так.
– supercat
10 October 2013 в 03:15
Более упрощенный ответ заключается в том, что NaN не имеет числового значения, поэтому нет ничего в этом, чтобы сравнивать с чем-либо еще.
Вы можете рассмотреть возможность тестирования и замены ваших NaN с помощью + INF, если вы хотите, чтобы они действовали как + INF.
NaN - неявный новый экземпляр (особый вид ошибки времени выполнения). Это означает NaN !== NaN
по той же причине, что new Error !== new Error
;
И помните, что такой имплициент также встречается вне ошибок, например, в контексте регулярных выражений это означает /a/ !== /a/
, который является просто синтаксическим сахаром для new RegExp('a') !== new RegExp('a')
x = NaN; x === x
, вы получите false
. Это отличается от Error: x = new Error; x === x
, который дает вам true
!
– dpercy
3 October 2017 в 03:51
Вставить еще одну аналогию. Если я передам вам две коробки и скажу вам, что ни один из них не содержит яблоко, вы могли бы сказать мне, что в ящиках есть одно и то же?
NaN не содержит информации о том, что что-то есть, что это такое «т. Поэтому эти элементы нельзя однозначно утверждать равными.
(NaN==Nan)==false
. То, что я не понимаю, является обоснованием для (Nan!=Nan)==true
.
– supercat
10 February 2014 в 22:19
Это выглядит только странно, потому что большинство программных сред, которые позволяют NaN, также не позволяют использовать 3-значную логику. Если вы выбросите 3-значную логику в микс, она станет последовательной:
Даже .NET не предоставляет оператора bool? operator==(double v1, double v2)
, так что вы все еще придерживаетесь глупых результатов (NaN == NaN) = false
.
Хотя я согласен, что сравнение NaN с любым реальным числом должно быть неупорядоченным, я думаю, что есть просто причина для сравнения NaN с самим собой. Как, например, можно обнаружить разницу между сигнальными NaN и тихими NaN? Если мы думаем о сигналах как о наборе булевых значений (т. Е. Битовом векторе), можно спросить, являются ли битовые векторы одинаковыми или разными и упорядочивают их соответственно. Например, при декодировании максимального смещенного экспоненты, если значение было сдвинуто влево, чтобы выровнять самый старший бит значащего в наиболее значимом бите двоичного формата, отрицательным значением будет тихое NaN, и любое положительное значение будет быть сигнальным NaN. Конечно, нуль зарезервирован для бесконечности, и сравнение будет неупорядоченным. Выравнивание MSB позволило бы прямое сравнение сигналов даже из разных двоичных форматов. Таким образом, два NaN с одинаковым набором сигналов будут эквивалентны и придают смысл равенству.
Для меня самый простой способ объяснить это:
У меня что-то есть, и если это не яблоко, то это оранжевый?
blockquote>Вы не можете сравнивать NaN с чем-то другим (даже самим собой), потому что он не имеет значения. Кроме того, это может быть любое значение (кроме числа).
У меня что-то есть, и если оно не равно числу, это строка?
blockquote>
Я не знаю конструктивного обоснования, но вот выдержка из стандарта IEEE 754-1985:
«Должно быть возможно сравнить числа с плавающей запятой во всех поддерживаемых форматах, даже если форматы операндов различаются. Сравнение точны и никогда не переполняются и не переполняются. Возможны четыре взаимоисключающих отношения: меньше, равно, больше и неупорядочено. Последний случай возникает, когда хотя бы один операнд - NaN. Каждый NaN будет сравнивать неупорядоченные с все, включая себя ».
Потому что математика - это поле, где числа «просто существуют». При вычислении вы должны инициализировать эти числа и сохранить свое состояние в соответствии с вашими потребностями. В те старые времена инициализация памяти работала так, как вы никогда не могли положиться. Вы никогда не могли позволить себе подумать об этом «о, это будет инициализировано с помощью 0xCD все время, мой алгоритм не сломается» .
Итак, вам нужно правильно не смешивающий растворитель, который достаточно липкий , чтобы не позволить вашему алгоритму всасываться и разрушаться. Хорошие алгоритмы с участием чисел в основном будут работать с отношениями, а отношения if () будут опущены.
Это просто смазка, которую вы можете поместить в новую переменную при создании, вместо того, чтобы программировать случайный ад из памяти компьютера. И ваш алгоритм, какой бы он ни был, не сломается.
Затем, когда вы все еще внезапно обнаруживаете, что ваш алгоритм производит NaNs, его можно очистить, глядя в каждую ветвь по одному. Опять же, правило «всегда ложное» очень помогает в этом.
Очень короткий ответ:
Потому что следующее:
nan / nan = 1
НЕ должно быть. В противном случае inf/inf
будет 1.
(Следовательно, nan
не может быть nan
. Что касается >
или <
, если nan
будет уважать любое отношение порядка в a множество, удовлетворяющее архимедовому свойству, мы бы снова nan / nan = 1
находились на пределе).
inf = inf
и inf / inf = nan
, поэтому nan = nan
не будет препятствовать nan / nan = nan
.
– starblue
4 June 2018 в 09:46
nan / nan = 1
? В любом случае ... Ваши рассуждения имеют смысл, если inf и nan были такими же, как и любые другие числа. Это не так. Причина, по которой inf/inf
должна быть nan
(или неопределенной формой в математике), а не 1
, является более тонкой, чем простая алгебраическая манипуляция (см. Теорему Де L'Госпиталя).
– SeF
7 June 2018 в 14:55
Из статьи wikipedia в NaN следующие методы могут приводить к NaNs:
Поскольку нет способа узнать, какая из этих операций создала NaN, нет никакого способа сравнить их, что имеет смысл.
1f/3f == 10000001f/30000002f
? Если значения с плавающей запятой считаются классами эквивалентности, тоa=b
не означает «Вычисления, которые далиa
иb
, если они выполнялись с бесконечной точностью, дали бы идентичные результаты», а скорее « То, что известно оa
, совпадает с тем, что известно оb
". Мне любопытно, знаете ли вы какие-либо примеры кода, где есть «Nan! = NaN». делает вещи проще, чем в противном случае? – supercat 21 August 2013 в 17:34