객체가 있고 그것의 메소드 중 하나가 PyQt 신호가 방출 될 때 실행되기를 원한다고 가정합니다. 그리고 신호로 전달되지 않는 매개 변수로 그렇게하기를 원한다고 가정합니다. 그래서 신호의 슬롯으로 람다 작성 : 일반적으로 PyQt는 신호와 슬롯, 이제람다에있는 객체의 수명이 pyqtSignal에 연결됨
class MyClass(object):
def __init__(self, model):
model.model_changed_signal.connect(lambda: self.set_x(model.x(), silent=True))
를, 신호 연결은 가비지 수집을 방지하지 않습니다. 연결된 슬롯의 객체가 가비지 수집되면 해당 신호가 방출 될 때 더 이상 슬롯이 호출되지 않습니다.
그러나 람다를 사용할 때 어떻게 작동합니까? 나는 람다에 대한 참조를 저장하지 않지만 신호 슬롯 연결은 계속 작동합니다. 따라서 람다는 가비지 수집되지 않습니다.
MyClass
의 인스턴스를 None
으로 설정하면 해당 인스턴스가 가비지 수집되지 않습니다. model_changed_signal
을 방출해도 여전히 람다가 실행됩니다. 그래서 분명히 MyClass
의 인스턴스에 대한 참조가 어딘가에있을 것입니다 (어쩌면 람다의 맥락에서)? 나는 원하지 않습니다.
왜 이런 일이 발생합니까?
람다가 MyClass 및 MyModel에 대한 참조를 유지하고 있음을 확인하고 명확히합니다. 감사합니다!내 남은 불명예는 lambda의 가비지 수집이 다른 함수 객체와 다른 이유입니다. 클래스를 인스턴스화하고 메소드 중 하나를'model.model_changed_signal.connect (ModelListener(). handle_signal)'과 연결하면'ModelListener'의 인스턴스가 가비지 컬렉팅되고'handle_signal'은 결코 사라지지 않을 것입니다. 라는. – tjalling
@tjalling. 쓰레기 수렴은 람다와 똑같습니다. 그 차이점은 전적으로 클로저 때문이며, * 모든 * 함수는 그 중 하나를 형성 할 수 있습니다. 함수가 아니라 참조를 유지하는 클로저입니다. 귀하의 의견에 주어진 예문에는 종결 조항이 없습니다. – ekhumoro
하지만 클로저에 대한 참조가 필요하지 않습니까? 람다에 대한 마지막 참조를 버리면 (예 : 'None'으로 설정) 람다와 해당 클로저가 가비지 수집됩니다. 맞습니까? 왜 람다를 'pyqtSignal'에 연결하면 람다 (그리고 클로저)가 쓰레기 수집되는 것을 막을 수있는 반면, 바운드 함수를 신호에 연결한다고해서 함수가 바인딩 된 객체가 가비지 수집되는 것을 막을 수는 없습니다. 모은? – tjalling