Оператор == всегда предназначен для сравнения ссылок на объекты, тогда как метод сравнения строк .equals () переопределяется для сравнения содержимого:
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)
lambda
в вашем примере образует закрытие. То есть, это вложенная функция, которая ссылается на объекты, доступные в охватывающей области. Каждая функция, которая создает замыкание, сохраняет объект ячейки для каждого элемента, который должен поддерживать ссылку.
В вашем примере lambda
создает замыкание со ссылками на локальные переменные self
и model
в рамках метода __init__
. Если вы где-нибудь ссылаетесь на lambda
, вы можете проверить все объекты ячейки его закрытия с помощью атрибута __closure__
. В вашем примере это будет выглядеть примерно так:
>>> print(func.__closure__)
(<cell at 0x7f99c16c5138: MyModel object at 0x7f99bbbf0948>, <cell at 0x7f99c16c5168: MyClass object at 0x7f99bbb81390>)
Если вы удалили все другие ссылки на объекты MyModel
и MyClass
, показанные здесь, те, которые хранятся в ячейках, все равно останутся. Поэтому, когда дело доходит до очистки объекта, вы всегда должны явно отключать все сигналы, связанные с функциями, которые могут образовывать замыкания по соответствующим объектам.
Обратите внимание, что когда дело доходит до соединений с сигналом / слотом, PyQt рассматривает обернутые слоты C ++ и методы экземпляра Python по-разному. Контрольные числа этих типов вызываемых не увеличиваются, когда они связаны с сигналами, тогда как lambdas, определенные функции, частичные объекты и статические методы. Это означает, что если все другие ссылки на последние типы вызываемых удаляются, любые оставшиеся сигнальные соединения будут поддерживать их. Отключение сигналов позволяет при необходимости собирать собранные связанные вызовы.
Единственное исключение из вышеперечисленного - методы класса. PyQt создает специальную оболочку при создании подключений к ним, поэтому, если все другие ссылки на них удаляются, и сигнал испускается, будет генерироваться исключение, например:
TypeError: 'managedbuffer' object is not callable
Вышеприведенное должно применяться к PyQt5 и большинству версий PyQt4 (4.3 и выше).
model.model_changed_signal.connect(ModelListener().handle_signal)
, экземплярModelListener
- сбор мусора, аhandle_signal
никогда не будет вызван. – tjalling 23 December 2017 в 16:47None
), лямбда и соответствующее закрытие будут собраны в мусор, верно? Почему подключение лямбда кpyqtSignal
предотвращает сбор лямбда (и закрытие) от сбора мусора, а привязка связанной функции к сигналу не препятствует тому, чтобы объект (к которому привязана функция) собрали? – tjalling 24 December 2017 в 13:30