使用Python实现一个类似Qt的信号、槽函数的class
class Signal:def __init__(self, *arg_types):self.__subscribers = []self.__arg_types = arg_typesdef connect(self, func):self.__subscribers.append(func)def disconnect(self, func):try:self.__subscribers.remove(func)except ValueError:print("Warning: function not found in the list of subscribers.")def emit(self, *args):# 检查传入参数的类型if len(args) != len(self.__arg_types):raise ValueError("Argument count mismatch")for arg, arg_type in zip(args, self.__arg_types):if not isinstance(arg, arg_type):raise TypeError(f"Argument {arg} does not match {arg_type}")# 如果所有检查都通过,则调用每个订阅者for subscriber in self.__subscribers:subscriber(*args)# 示例使用
if __name__ == "__main__":# 创建一个信号,指定它将发射一个str类型和一个int类型的数据signal = Signal(str, int)# 定义一个槽函数,接收一个str和一个intdef slot(message, number):print(f"Received message: {message}, number: {number}")# 连接信号到槽函数signal.connect(slot)# 正确使用,符合类型要求signal.emit("Test", 42)# 尝试发射错误的类型,将引发TypeErrortry:signal.emit("Another Test", "not a number")except TypeError as e:print(f"TypeError: {e}")
这段代码实现了一个简单的信号-槽(Signal-Slot)机制,类似于Qt框架中的信号与槽。某个事件发生(信号)时通知一个或多个接收者(槽)进行响应:
-
Signal
类初始化 (__init__
方法):- 当一个
Signal
对象被创建时,它可以接受任意数量的参数类型作为其构造函数的参数。这些参数类型将存储在self.__arg_types
中,用来校验发射信号时传递的参数类型是否正确。 self.__subscribers
是一个列表,用来存储所有连接到这个信号的函数(订阅者)。
- 当一个
-
connect
方法:- 该方法接受一个函数(
func
)作为参数,并将这个函数添加到self.__subscribers
列表中。每当信号发射时,这个函数将被调用。
- 该方法接受一个函数(
-
disconnect
方法:- 该方法用于移除一个已连接的函数。如果该函数存在于
self.__subscribers
列表中,它将被移除。如果函数不存在,则打印一条警告信息。
- 该方法用于移除一个已连接的函数。如果该函数存在于
-
emit
方法:- 这是信号发射的核心方法。它接受任意数量的参数,这些参数将被传递给所有连接到该信号的函数。
- 在传递参数给订阅者之前,
emit
方法首先校验参数的数量是否与初始化信号时指定的类型数量一致;接着校验每个参数的类型是否与相应的self.__arg_types
中指定的类型匹配。如果参数的数量或类型不匹配,则抛出异常。 - 一旦检查通过,
emit
方法将遍历self.__subscribers
列表,并依次调用其中的每个函数,将信号的参数传递给这些函数。
在使用时,引入这个类即可。