使用Python实现一个类似Qt的信号、槽函数的class
python
class Signal:
def __init__(self, *arg_types):
self.__subscribers = []
self.__arg_types = arg_types
def 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和一个int
def slot(message, number):
print(f"Received message: {message}, number: {number}")
# 连接信号到槽函数
signal.connect(slot)
# 正确使用,符合类型要求
signal.emit("Test", 42)
# 尝试发射错误的类型,将引发TypeError
try:
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
列表,并依次调用其中的每个函数,将信号的参数传递给这些函数。
在使用时,引入这个类即可。