кортеж ценности и идентичности идентичны, но тестирование идентичности (есть) получает false в python [duplicate]

Я нашел проблему действительно интересной, поэтому я решил попробовать. Я не знаю о pythonic или естественном, но я думаю, что нашел более точный способ привязки к набору данных, подобному вашему, при использовании информации из каждой точки .

Прежде всего, давайте создадим случайные данные, которые выглядят так, как показано на рисунке. Эта часть может быть легко пропущена, я отправляю ее просто так, чтобы код был полным и воспроизводимым. Я использовал два двумерных нормальных распределения для имитации этих сверхплотностей и посыпал их слоем равномерно распределенных случайных точек. Затем они были добавлены к линейному уравнению, аналогичному вашему, и все под строкой было отрезано, и конечный результат выглядел следующим образом:

Вот фрагмент кода, чтобы сделать это :

import numpy as np

x_res = 1000
x_data = np.linspace(0, 2000, x_res)

# true parameters and a function that takes them
true_pars = [80, 70, -5]
model = lambda x, a, b, c: (a / np.sqrt(x + b) + c)
y_truth = model(x_data, *true_pars)

mu_prim, mu_sec = [1750, 0], [450, 1.5]
cov_prim = [[300**2, 0     ],
            [     0, 0.2**2]]
# covariance matrix of the second dist is trickier
cov_sec = [[200**2, -1     ],
           [    -1,  1.0**2]]
prim = np.random.multivariate_normal(mu_prim, cov_prim, x_res*10).T
sec = np.random.multivariate_normal(mu_sec, cov_sec, x_res*1).T
uni = np.vstack([x_data, np.random.rand(x_res) * 7])

# censoring points that will end up below the curve
prim = prim[np.vstack([[prim[1] > 0], [prim[1] > 0]])].reshape(2, -1)
sec = sec[np.vstack([[sec[1] > 0], [sec[1] > 0]])].reshape(2, -1)

# rescaling to data
for dset in [uni, sec, prim]:
    dset[1] += model(dset[0], *true_pars)

# this code block generates the figure above:
import matplotlib.pylab as plt
plt.figure()
plt.plot(prim[0], prim[1], '.', alpha=0.1, label = '2D Gaussian #1')
plt.plot(sec[0], sec[1], '.', alpha=0.5, label = '2D Gaussian #2')
plt.plot(uni[0], uni[1], '.', alpha=0.5, label = 'Uniform')
plt.plot(x_data, y_truth, 'k:', lw = 3, zorder = 1.0, label = 'True edge')
plt.xlim(0, 2000)
plt.ylim(-8, 6)
plt.legend(loc = 'lower left')
plt.show()

# mashing it all together
dset = np.concatenate([prim, sec, uni], axis = 1)

Теперь, когда у нас есть данные и модель, мы можем провести мозговой штурм, как установить край точечного распределения. Обычно используемые методы регрессии, такие как нелинейные наименьшие квадраты scipy.optimize.curve_fit, принимают значения данных y и оптимизируют свободные параметры модели, так что остаточные значения между y и model(x) минимальны. Нелинейные наименьшие квадраты - это итерационный процесс, который на каждом шаге пытается изменять параметры кривой на каждом шаге, чтобы улучшить соответствие на каждом шаге. Теперь ясно, что это одна вещь, которую мы не хотим делать , так как мы хотим, чтобы наша процедура минимизации позволяла нам как можно дальше от наилучшей кривой (но не ] далеко.)

Итак, вместо этого рассмотрим следующую функцию. Вместо простого возврата остатка он будет также «переворачивать» точки над кривой на каждом шаге итерации и также учитывать их. Таким образом, на кривой всегда есть больше очков, чем выше, что приводит к смещению кривой с каждой итерацией! Как только самые низкие точки достигнуты, был найден минимум функции, а также край разброса. Конечно, этот метод предполагает, что у вас нет выбросов ниже кривой - но тогда ваша фигура, похоже, не сильно их подвергает.

Вот функции, реализующие эту идею:

def get_flipped(y_data, y_model):
    flipped = y_model - y_data
    flipped[flipped > 0] = 0
    return flipped

def flipped_resid(pars, x, y):
    """
    For every iteration, everything above the currently proposed
    curve is going to be mirrored down, so that the next iterations
    is going to progressively shift downwards.
    """
    y_model = model(x, *pars)
    flipped = get_flipped(y, y_model)
    resid = np.square(y + flipped - y_model)
    #print pars, resid.sum() # uncomment to check the iteration parameters
    return np.nan_to_num(resid)

Посмотрим, как это выглядит выше:

# plotting the mock data
plt.plot(dset[0], dset[1], '.', alpha=0.2, label = 'Test data')

# mask bad data (we accidentaly generated some NaN values)
gmask = np.isfinite(dset[1])
dset = dset[np.vstack([gmask, gmask])].reshape((2, -1))

from scipy.optimize import leastsq
guesses =[100, 100, 0]
fit_pars, flag = leastsq(func = flipped_resid, x0 = guesses,
                         args = (dset[0], dset[1]))
# plot the fit:
y_fit = model(x_data, *fit_pars)
y_guess = model(x_data, *guesses)
plt.plot(x_data, y_fit, 'r-', zorder = 0.9, label = 'Edge')
plt.plot(x_data, y_guess, 'g-', zorder = 0.9, label = 'Guess')
plt.legend(loc = 'lower left')
plt.show()

Самой важной частью выше является вызов функции leastsq. Удостоверьтесь, что вы осторожны с первоначальными догадками - если угадание не падает на разброс, модель может не сходиться должным образом. После того, как уместно угадать ...

Voilà! Край отлично соответствует реальному.

924
задан BuZZ-dEE 20 November 2015 в 14:28
поделиться

15 ответов

Это побочная заметка, но в идиоматическом питоне вы часто увидите такие вещи, как:

if x is None: 
    # some clauses

Это безопасно, потому что гарантированно будет один экземпляр объекта Null (т. е. None) .

1234
ответ дан SilentGhost 18 August 2018 в 19:02
поделиться
  • 1
    ahh же, как eq? vs равно? в схеме, получил его. – jottos 1 October 2009 в 18:00
  • 2
    В Common Lisp существует много предикатов равенства, помимо базовой иерархии eq, eql, equal и equalp (чем дольше будет имя, тем больше будет найдено одинаковое). – David Thornley 1 October 2009 в 20:43
  • 3
    Или == vs .equals() в Java. Наилучшая часть состоит в том, что Python == не похож на Java ==. – MatrixFrog 4 February 2012 в 04:48
  • 4
    @ Крайст: существует только одно значение None. Таким образом, он всегда имеет один и тот же идентификатор. – SilentGhost 29 October 2012 в 11:57
  • 5
    Это не относится к OP's is is - & gt; Правда & Quot; пример. – user2864740 10 September 2014 в 05:53
  • 6
    Я обдумывал это. вдруг я увидел ваш ответ! – Juggernaut 19 January 2017 в 16:44
  • 7
    То же самое верно для True и False? Будет только один экземпляр? – HandyManDan 1 June 2018 в 18:00
1242
ответ дан SilentGhost 7 September 2018 в 03:18
поделиться
1273
ответ дан SilentGhost 30 October 2018 в 07:28
поделиться

is - тестирование идентичности, == - тестирование равенства (см. Документация Python ).

В большинстве случаев, если a is b, то a == b. Но есть исключения, например:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

Таким образом, вы можете использовать is для тестирования идентичности, никогда не проводить тесты равенства.

1
ответ дан Christian König 18 August 2018 в 19:02
поделиться

Другие ответы здесь верны: is используется для сравнения identity , а == используется для сравнения равенство . Поскольку вам нужно заботиться о равенстве (две строки должны содержать одни и те же символы), в этом случае оператор is просто ошибочен, и вы должны использовать вместо него ==.

Причина is работает интерактивно, что (большинство) строковых литералов по умолчанию interned . Из Wikipedia:

Интернированные строки ускоряют сопоставления строк, которые иногда являются узким местом производительности в приложениях (например, компиляторами и языками динамического программирования), которые в значительной степени зависят от хэш-таблиц со строковыми ключами. Без интернирования проверка того, что две разные строки равны, включает в себя изучение каждого символа обеих строк. Это медленно по нескольким причинам: по своей сути это O (n) в длине строк; обычно требуется чтение из нескольких областей памяти, которые требуют времени; и чтение считывает кеш процессора, что означает, что для других нужд меньше кеша. С интернированными строками после первоначальной статической операции достаточно простого теста на идентификацию объекта; это обычно реализуется как тест равенства указателя, обычно это всего лишь одна машинная команда без ссылки на память.

Итак, когда у вас есть два строковых литерала (слова, которые буквально введены в ваш исходный код программы, окруженный кавычками) в вашей программе, имеющей то же значение, компилятор Python автоматически ставит строки, делая их оба сохраненными в том же месте памяти. (Обратите внимание, что это не всегда всегда , а правила для того, когда это происходит, довольно запутаны, поэтому, пожалуйста, не полагайтесь на это поведение в производственном коде!) [/ ​​G12]

Поскольку в вашем интерактивном сеансе обе строки фактически хранятся в одном и том же месте памяти, у них одинаковое identity , поэтому оператор is работает так, как ожидалось. Но если вы построите строку другим способом (даже если эта строка содержит точно одинаковые символы), то строка может быть равна , но это не одна и та же строка , то есть она имеет другое тождество , поскольку оно хранится в другом месте в памяти.

442
ответ дан Daniel Pryden 18 August 2018 в 19:02
поделиться
  • 1
    Где кто-то может прочитать больше о запутанных правилах, когда строки интернированы? – Noctis Skytower 11 April 2013 в 15:14
  • 2
    +1 для подробного объяснения. Не уверен, как в другом ответе было так много упреков, не объяснив, что НАСТОЯТЕЛЬНО произошло. – That1Guy 29 April 2013 в 03:07
  • 3
    это именно то, о чем я думал, когда я читал вопрос. Принятый ответ короткий, но содержит факт, но этот ответ объясняет вещи намного лучше. Ницца! – Sнаđошƒаӽ 19 July 2015 в 05:46
  • 4
    @NoctisSkytower Googled то же самое и нашел это guilload.com/python-string-interning – xtreak 10 March 2016 в 15:41
  • 5
    @ naught101: Нет, правило состоит в том, чтобы выбрать между == и is в зависимости от того, какую проверку вы хотите. Если вам нужны строки equal (то есть, имеющие одинаковое содержимое), вы всегда должны использовать ==. Если вам небезразлично, ссылаются ли какие-либо два имени Python на один и тот же экземпляр объекта, вы должны использовать is. Возможно, вам понадобится is, если вы пишете код, который обрабатывает множество разных значений, не заботясь об их содержимом, иначе, если вы знаете, что есть только один из них, и вы хотите игнорировать другие объекты, претендующие на то, что они есть. Если вы не уверены, всегда выбирайте ==. – Daniel Pryden 18 October 2016 в 19:30

Из моего ограниченного опыта работы с python is используется для сравнения двух объектов, чтобы увидеть, являются ли они одним и тем же объектом, а не двумя разными объектами с одинаковым значением. == используется для определения идентичности значений.

Вот хороший пример:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 - строка в Юникоде, а s2 - обычная строка. Они не одного типа, но имеют одинаковое значение.

16
ответ дан Jack M. 18 August 2018 в 19:02
поделиться
  • 1
    Ваш пример по-прежнему следует за старым текстом .... – jprete 2 October 2009 в 17:16

В последнее время вы можете использовать функцию intern, чтобы убедиться, что вы получаете ссылку на одну и ту же строку:

>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

Как указано выше, вы, вероятно, не должны делать является определение равенства по строкам. Но это может быть полезно узнать, есть ли у вас какое-то странное требование использовать is.

Обратите внимание, что функция-интернатура перешла из встроенной функции в модуль sys для Python 3.

48
ответ дан Jason Baker 18 August 2018 в 19:02
поделиться

is сравнивает местоположение памяти. Он используется для сравнения уровня объекта.

== будет сравнивать переменные в программе. Он используется для проверки на уровне ценности.

is проверяет эквивалентность уровня адреса

== проверяет эквивалентность уровня значения

0
ответ дан johnashu 18 August 2018 в 19:02
поделиться

Если вы не уверены, что делаете, используйте '=='. Если у вас есть немного больше знаний об этом, вы можете использовать «is» для известных объектов, таких как «None».

В противном случае вы будете удивлены, почему все не работает и почему это происходит:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

Я даже не уверен, что некоторые вещи гарантированно останутся неизменными между различными версиями / реализациями python.

23
ответ дан Mattias Nilsson 18 August 2018 в 19:02
поделиться
  • 1
    Интересный пример показывает, как переназначение int делает триггеры этим условием. Почему это не удалось? Это связано с интернированием или чем-то еще? – Paul 22 December 2014 в 17:49
  • 2
    Похоже, причина, по которой возвращает false, может быть вызвана реализацией интерпретатора: stackoverflow.com/questions/132988/… – Paul 22 December 2014 в 17:55
  • 3
  • 4
    @ArchitJain Да, эти ссылки объясняют это довольно хорошо. Когда вы их прочтете, вы узнаете, какие цифры вы можете использовать «есть». Я просто хочу, чтобы они объяснили, почему это еще не очень хорошая идея. Знаете ли вы, что это не значит, что предположить, что все остальное тоже (или что интернализованный диапазон номеров никогда не изменится) – Mattias Nilsson 29 December 2015 в 14:32

Я думаю, что это связано с тем, что, когда сравнение «is» оценивается как false, используются два разных объекта. Если он оценивает значение true, это означает, что внутри он использует один и тот же точный объект, а не создает новый, возможно, потому, что вы создали их за долю в 2 или около того секунд и потому, что между ним нет большого промежутка времени и использует тот же объект.

Вот почему вы должны использовать оператор равенства ==, а не is, чтобы сравнить значение строкового объекта.

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

В этом примере я сделал s2, который был другим строковым объектом, ранее равным «одному», но это не тот же объект, что и s, потому что интерпретатор не использовал тот же объект, что и я, один ', если бы я сделал это, это сделало бы их одним и тем же объектом.

12
ответ дан meder omuraliev 18 August 2018 в 19:02
поделиться
  • 1
    Использование .replace() в качестве примера в этом контексте, вероятно, не самое лучшее, хотя, поскольку его семантика может сбить с толку. s2 = s2.replace() будет всегда создавать строковый объект new , назначить новый строковый объект на s2, а затем удалить строковый объект, который s2 использовал для указания на , Поэтому, даже если вы s = s.replace('one', 'one'), вы все равно получите новый строковый объект. – Daniel Pryden 1 October 2009 в 17:20
  • 2
    Ах, хорошая точка, и это правда. – meder omuraliev 1 October 2009 в 17:46

is - тестирование идентичности, == - проверка равенства. Это означает, что is - это способ проверить, являются ли две вещи одинаковыми вещами или просто эквивалентны.

Скажем, у вас есть простой объект person. Если он называется «Джек» и ему «23 года», он эквивалентен другому 23-летнему Джеку, но его не одному человеку.

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 #True
jack1 is jack2 #False

Они того же возраста, не один и тот же экземпляр человека. Строка может быть эквивалентна другой, но это не тот же объект.

30
ответ дан Morgan Thrapp 18 August 2018 в 19:02
поделиться

Я отвечаю на вопрос, даже если вопрос старен, потому что ни один из ответов выше не цитирует ссылку на язык

На самом деле оператор проверяет идентификаторы и == проверяет оператор на равенство,

Из справочника по языку:

Типы затрагивают почти все аспекты поведения объекта. Даже значение идентичности объектов в некотором смысле влияет: для неизменяемых типов операции, которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после a = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один, в зависимости от реализации, но после c = []; d = [], c и d гарантированно относятся к двум различным уникальным, вновь созданным пустым спискам. (Обратите внимание, что c = d = [] присваивает один и тот же объект как c, так и d.)

, поэтому из вышеприведенного утверждения мы можем заключить, что строки, которые являются неизменяемым, могут сбой при проверке с помощью «is» и может проверяться успешно, если отмечено с помощью «is»

То же самое относится к int, кортежу, которые также являются неизменяемыми типами

9
ответ дан Ram 18 August 2018 в 19:02
поделиться

Ключевое слово is - это тест для идентификации объекта, а == - сравнение значений.

Если вы используете is, результат будет истинным тогда и только тогда, когда объект является тот же объект. Однако == будет истинным в любое время, когда значения объекта будут одинаковыми.

94
ответ дан Thomas Owens 18 August 2018 в 19:02
поделиться

Эквивалентность тестового значения оператора ==. Оператор is проверяет идентичность объекта, Python проверяет, действительно ли эти два являются одним и тем же объектом (т. Е. Живут по одному и тому же адресу в памяти).

>>> a = 'banana'
>>> b = 'banana'
>>> a is b 
True

В этом примере Python создал только одну строку объект, и оба a и b ссылаются на него. Причина в том, что Python внутренне кэширует и использует несколько строк в качестве оптимизации, на самом деле в памяти есть только строка «банан», разделяемая a и b; Чтобы вызвать нормальное поведение, вам нужно использовать более длинные строки:

>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)

Когда вы создаете два списка, вы получаете два объекта:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

В этом случае мы сказали бы: что эти два списка эквивалентны, потому что они имеют одинаковые элементы, но не идентичны, потому что они не являются одним и тем же объектом. Если два объекта идентичны, они также эквивалентны, но если они эквивалентны, они не обязательно идентичны.

Если a ссылается на объект и вы назначаете b = a, то обе переменные ссылаются на тот же объект:

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
3
ответ дан X. Wang 18 August 2018 в 19:02
поделиться

Я считаю, что это известно как «интернированные» строки. Python делает это, так же как и Java, а также C и C ++ при компиляции в оптимизированных режимах.

Если вы используете две идентичные строки, вместо того, чтобы тратить память на создание двух строковых объектов, все интернированные строки с одинаковыми содержимое указывает на одну и ту же память.

Это приводит к тому, что оператор Python «is» возвращает True, потому что две строки с тем же содержимым указывают на один и тот же строковый объект. Это также произойдет в Java и в C.

Это полезно только для экономии памяти. Вы не можете полагаться на него, чтобы проверить равенство строк, потому что различные интерпретаторы, компиляторы и JIT-механизмы не всегда могут это сделать.

11
ответ дан Zan Lynx 18 August 2018 в 19:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: