ContextMenu
: Проблема заключается в том, что параметр sender
указывает на пункт в контекстном меню, которое было нажато, а не на контекстное меню.
Это простое исправление, потому что каждый MenuItem
предоставляет метод GetContextMenu
, который расскажет вам, какой ContextMenu
содержит этот пункт меню.
Измените свой код на следующее:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a MenuItem
MenuItem menuItem = sender as MenuItem;
if (menuItem != null)
{
// Retrieve the ContextMenu that contains this MenuItem
ContextMenu menu = menuItem.GetContextMenu();
// Get the control that is displaying this context menu
Control sourceControl = menu.SourceControl;
}
}
ContextMenuStrip
: Это немного изменит ситуацию, если вы используете ContextMenuStrip
вместо ContextMenu
, Два элемента управления не связаны друг с другом, и экземпляр одного не может быть передан экземпляру другого.
Как и прежде, элемент , который был нажат, все еще возвращен в параметре sender
, поэтому вам нужно будет определить ContextMenuStrip
, которому принадлежит этот отдельный пункт меню. Вы делаете это с помощью свойства Owner
. Наконец, вы будете использовать свойство SourceControl
, чтобы определить, какой элемент управления отображает контекстное меню.
Измените свой код следующим образом:
private void MenuViewDetails_Click(object sender, EventArgs e)
{
// Try to cast the sender to a ToolStripItem
ToolStripItem menuItem = sender as ToolStripItem;
if (menuItem != null)
{
// Retrieve the ContextMenuStrip that owns this ToolStripItem
ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;
if (owner != null)
{
// Get the control that is displaying this context menu
Control sourceControl = owner.SourceControl;
}
}
}
is
возвратится True
, если две переменные укажут на тот же объект, ==
, если объекты, упомянутые переменными, равны.
>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
>>> b == a
True
>>> b = a[:] # Make a new copy of list `a` via the slice operator, and assign it to variable `b`
>>> b is a
False
>>> b == a
True
В Вашем случае, второй тест только работает, потому что кэши Python маленькие целочисленные объекты, который является деталью реализации. Для больших целых чисел это не работает:
>>> 1000 is 10**3
False
>>> 1000 == 10**3
True
то же сохраняется для строковых литералов:
>>> "a" is "a"
True
>>> "aa" is "a" * 2
True
>>> x = "a"
>>> "aa" is x * 2
False
>>> "aa" is intern(x*2)
True
см. этот вопрос также.
Разница в Python между is и equals (==)
Оператор is может выглядеть так же, как оператор равенства, но они не одинаковы.
is проверяет, указывают ли обе переменные на один и тот же объект, тогда как знак == проверяет, совпадают ли значения двух переменных.
Таким образом, если оператор is возвращает True, тогда равенство определенно True, но обратное может быть или не быть True.
Вот пример, чтобы продемонстрировать сходство и различие.
>>> a = b = [1,2,3]
>>> c = [1,2,3]
>>> a == b
True
>>> a == c
True
>>> a is b
True
>>> a is c
False
>>> a = [1,2,3]
>>> b = [1,2]
>>> a == b
False
>>> a is b
False
>>> del a[2]
>>> a == b
True
>>> a is b
False
Tip: Avoid using is operator for immutable types such as strings and numbers, the result is unpredictable.
На самом деле я хотел добавить это как комментарий, но не мог украсить его легко, поэтому добавлял как ответ, пожалуйста, не рассматривайте это как ответ.
Это то, что я сделал, чтобы понять -
выполнять следующие один за другим и понимать вывод на каждом шаге
a = [1,2]
b = [1,2,3]
b.pop()
id(a)
id(b)
a is b
a == b
https://тесты docs.python.org/library/stdtypes.html#comparisons
is
для идентификационных данных ==
тесты для равенства
Каждое (маленькое) целочисленное значение отображается на единственном значении, таким образом, каждые 3 идентичны и равны. Это - деталь реализации, не часть спецификации языка хотя
Как сказал Джон Феминелла, большую часть времени вы будете использовать == и! =, Потому что ваша цель - сравнить значения. Я просто хотел бы классифицировать то, что вы будете делать в остальное время:
Существует один и только один экземпляр NoneType, т.е. ни один не является синглтоном. Следовательно, foo == None
и foo is None
означают одно и то же. Тем не менее, тест is
быстрее, и Pythonic соглашается использовать foo is None
.
Если вы проводите некоторый самоанализ или разбираетесь со сборкой мусора или проверяете, работает ли ваш пользовательский встроенный гаджет для интернирования строк или тому подобное, то у вас, вероятно, есть вариант использования для foo
: bar
.
True и False также (в настоящее время) синглтоны, но для foo == True
нет сценария использования и для foo is True
.
==
определяет, равны ли значения, в то время как is
определяет, являются ли они тем же самым объектом и равный.
Они полностью отличающиеся . is
проверки на объектные идентификационные данные, в то время как ==
проверки на равенство (понятие, которое зависит от типов этих двух операндов).
Это - только удачное совпадение, которое" is
", кажется, работает правильно с маленькими целыми числами (например, 5 == 4+1). Это вызвано тем, что CPython оптимизирует устройство хранения данных целых чисел в диапазоне (-5 к 256) путем создания их одиночными элементами . Это поведение является полностью зависящим от реализации и не гарантировало, что было сохранено под всем способом незначительных поддающихся трансформации операций.
, Например, Python 3.5 также делает короткие строковые одиночные элементы, но разрезание их разрушает это поведение:
>>> "foo" + "bar" == "foobar"
True
>>> "foo" + "bar" is "foobar"
True
>>> "foo"[:] + "bar" == "foobar"
True
>>> "foo"[:] + "bar" is "foobar"
False
Существует простое эмпирическое правило, чтобы сказать вам, когда использовать ==
или is
.
==
для значения равенства . Используйте его, когда хотите узнать, имеют ли два объекта одинаковое значение. is
для эталонного равенства . Используйте его, когда хотите узнать, ссылаются ли две ссылки на один и тот же объект. В общем, когда вы сравниваете что-то с простым типом, вы обычно проверяете на равенство значений , поэтому вам следует использовать ==
. Например, целью вашего примера, вероятно, является проверка того, имеет ли x значение, равное 2 (==
), а не то, ссылается ли x
на тот же объект, что и 2.
Что еще нужно отметить: из-за того, как работает реализация ссылок CPython, вы получите неожиданные и противоречивые результаты, если по ошибке используете is
для сравнения на равенство ссылок на целых числах:
>>> a = 500
>>> b = 500
>>> a == b
True
>>> a is b
False
Это в значительной степени то, что мы ожидали: a
и b
имеют одинаковое значение, но являются разными сущностями. Но как насчет этого?
>>> c = 200
>>> d = 200
>>> c == d
True
>>> c is d
True
Это не согласуется с более ранним результатом. Что тут происходит? Оказывается, эталонная реализация Python кэширует целочисленные объекты в диапазоне -5..256 как единичные экземпляры по соображениям производительности. Вот пример, демонстрирующий это:
>>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
...
250: True
251: True
252: True
253: True
254: True
255: True
256: True
257: False
258: False
259: False
Это еще одна очевидная причина не использовать is
: поведение оставлено на усмотрение реализаций, когда вы ошибочно используете его для равенства значений.
Ваш ответ корректен. is
оператор сравнивает идентификационные данные двух объектов. ==
оператор сравнивает значения двух объектов.
идентификационные данные объекта никогда не изменяются, как только они были созданы; можно думать о нем как об адресе объекта в памяти.
можно управлять поведением сравнения объектных значений путем определения __cmp__
метод или богатое сравнение метод как __eq__
.
Have a look at Stack Overflow question Python's “is” operator behaves unexpectedly with integers.
What it mostly boils down to is that "is
" checks to see if they are the same object, not just equal to each other (the numbers below 256 are a special case).